优美的为js中的yield赋能

发布时间:2021年10月04日 阅读:13 次

yield是javascript关键字,被用来生成es6中的Generator,现在chrome的浏览器已经完美的支持了。

什么是Generator

当我们写一个函数 在function后面或者函数名字前面加上一个* 调用这个函数返回的就是Generator 而这个函数称为Generator函数

function *main(){
}

main() // -> [object Generator]

function *learn(){
  yield 1
  yield 2
  return 3
}

let learnGe = learn() // ->复制代码

   

Generator函数可以只运行函数的一部分以及控制何时运行函数的剩余部分

learnGe.next() // -> {"done": false, "value": 1}复制代码

   

done 表示 learn函数未运行完毕value 表示 learn函数中 yield 1中的 1

再次调用next()会运行到下一个 yield之处

learnGe.next() // -> {"done": false, "value": 2}
learnGe.next() // -> {"done": true, "value": 3}复制代码

   

最后运行之return之处 done为true ,value是return 的返回值

Generator的强大之处

学习前面的介绍根本体现不了yield的强大之处,原因是有一个重点并没有介绍,它就是:

可以给learnGe.next函数传递参数 这个参数可以作为yield的返回值(注意:一定要动手实验)

function *withParam(){
  let a = yield "a"
  return a
}

let withParamGe = withParam()
let wr = withParamGe.next()
withParamGe.next("hello " + wr.value) 
// -> {"done": true, "value": "hello a"}复制代码

   

看到了吗 我们可以操作yield后面的参数 和 其返回值之间的转换

来试试 让yield 直接提取异步接口返回的数据

假设我们有一个请求http接口函数 http.get(url) -> Promise Data Error 传递url返回数据

function *mylogic(){
   let data = yield http.get('/your/path')
   your loginc ..
}
function runMyPromise(ge,val){
  let a = get.next(val)
  if(a.done){
   return a.value
  }else {
    return a.then(data=>runMyPromise(ge,a.value))
  }
}
runMyPromise(mylogic())复制代码

   

这样我们就可以像写同步代码一样写异步代码了

为Generator赋能

上面铺垫了这么多就是为了在这里给yield赋能,经过yield之后的数据 都能得到我想要的数据,我把这个功能封装到一个函数里面 runIWant

实现的功能如下

let a = yield Promise data error -> 返回Promise 中的data

let b = yield Generator val -> 返回 Generator中的val (注:这里的val指的是Generator函数的返回值)

let c = yield 其它 -> 返回其它本身

let d = yield Nothing -> 直接退出运行 返回Nothing

如果Generator里面没有Promise data error 同步返回值否则返回Promise val error

function isPromise(a){
  return Object.prototype.toString.call(a) === "[object Promise]"
}
function isGenerator(a){
  return Object.prototype.toString.call(a) === "[object Generator]"
}
const Nothing = Symbol('Nothing')
const ToValue = Symbol('ToValue')
function isToValue(a){
  return a && (typeof a[ToValue] === 'function')
}
function runIWant(ge,gval){
  gval = gval || {done: false,value:undefined}
  if ( gval.done) {
    return gval.value
  } else if (isPromise(gval.value)) {
    return gval.value.then(data=>{
      return runIWant(ge,ge.next(data))
    })
  } else if (isGenerator(gval.value)) {
    return runIWant(ge,ge.next(runIWant(gval.value)))
  } else if (gval.value === Nothing) {
    return runIWant(ge,ge.return(Nothing))
  }else {
    return runIWant(ge,ge.next(gval.value))
  }
}复制代码

   

代码一共就上面这点(注:有些是手工输入打去的并没有经过测试,如果有错误请指出)

function *getName(){
  let user = yield http.get('get/user')
  return user.name
}
function *main(){
  let name = yield getName()
  console.log('My name is ' + name)  
}复制代码

   

这些代码可以直接在chrome repl中运行 无需babel


作者:已禁用
链接:https://juejin.cn/post/6844903538296881165


Tag:yield js js代码
相关文章

发表评论: