Getting a promise's value via yield & co

拥有回忆 提交于 2019-11-29 06:23:23

Yes, co can do that. You'll have to wrap parent function inside co call:

co(function *(){
    var someVar = yield functionThatReturnsAPromise();
})()

someVar inside will become resolved value. If promise gets rejected, error can be cought with basic try {} catch (e) {} statements.

Typically a yield acts returns the same value to its own paused execution (left hand side of the yield function) as to the calling function of the generator. In this simple example counting from 1 to 5 example the input of the yield is the output of the yield to the generator function as well as to the generator's execution path:

function* inc() {
    var g = 0; 
    while (true) {
      g = yield g + 1;
    }
}

var incGen = inc();
for (i = incGen.next().value; i <= 5; i = incGen.next(i).value) {
  console.log(i);  //                                ^ input of generator is last output
}

However, the calling function may also call the generator, but replace the output the last yield with another value or even throw an exception to the generator's execution. In the case of promise a function that returns a promise, may yield the result of that promise instead of the promise itself. So in this case:

var someVar = yield functionThatReturnsAPromise();
     ^ output  !=   ^ input

you want the yield to act as a function that takes a promise as an input and returns a resolved promise as an output to the generator function.

It so happens co is able to do exactly this for you. All you need to do is feed your generator function to the co function:

co(function *(){
    var someVar = yield functionThatReturnsAPromise();
})

To better understand how this works, here is an example of a function, that does the same thing as co:

function async(makeGenerator){
  return function (){
    var generator = makeGenerator.apply(this, arguments)

    function handle(result){
      if (result.done) return result.value

      return result.value.then(function (res){
        return handle(generator.next(res))  // <- sets output of yield to the promise result
      }, function (err){                    //    and returns input promise 
        return handle(generator.throw(err)) // <- throw promise exception to generator function
      })
    }

    return handle(generator.next()) // <- first time call, input of yield is a promise
  }
}

source is from Forbes Lindesay's now famous presentation about this concept

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!