为js中yield赋能

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 为false表示 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"}


由结果可知,给next传递参数可以控制"a"到变量a之间的转换。


一个很实用的地方,利用yield取出异步的『返回值』,使Generator函数看起来就像同步一样。

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

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())

runMyPromise函数取出Promise中的data,通过Generator的特性赋值给 mylogic函数中的data,mylogic函数中的异步调用看起来就像同步一样简单。不,可以说就是同步代码了。

为Generator赋能


上面铺垫了这么多就是为了在这里给yield赋能,通过yield关键字,我们可以控制yield后面的表达式和yield前面赋值的关系——简单说就是控制怎样赋值的,如前面yield Promise是取出Promise中的data去赋值。除了Promise可能还想控制其它的赋值关系,我将它封装到一个函数中runIWant。

实现的功能如下

let a = yield Promise JSON Error -> 返回Promise 中的JSON

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

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

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


如果Generator函数没有遇到Promise同步返回值,否则返回Promise中的data

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


备注:

Promise JSON Error 是指 Psomise类型 then取出的类型JSON,catch取出的类型是Error,

「let money = yield 知乎赞赏」
赞赏
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值