co.wrap = function(gen) {
var idt = gen(resume)
function resume() {
var args = arguments
process.nextTick(function() {
var obj = idt.next(args).value
if (obj && isPromise(obj))
obj.then(
(res) => {
resume(null, res)
},
(err) => resume(err)
)
})
}
return resume
}
co.run = function(gen) {
co.wrap(gen)()
}
co.run(function * ($) {
// yield
})
function isPromise(obj) {
return 'function' == typeof obj.then;
}
对应这句代码我不是很理解: resume(null, res)
望指教
原来我不理解是因为:
不懂为什么要递归呢?
是为了继续运行生成器函数,直到返回 Object { value: undefined, done: true }
resume(null, res)
传的参数是干什么用的呢?
实际上是将结果传回去,类似这个
function* gen() {
while(true) {
var value = yield null;
console.log(value);
}
}
var g = gen();
g.next(1);
// "{ value: null, done: false }"
g.next(2);
// "{ value: null, done: false }"
// 2
等我想好了,我会告诉大家使用process.nextTick( )的意义。
估计就相当于callback
吧,即callback(null,res)
,因为没有error
所以给了null
了
不要问为什么,我也是猜的
@imhered 没想问为什么,因为你根本没讲到点上。原谅我说话很直。。。
const co = {};
co.wrap = function(gen) {
var idt = gen(resume) //idt 是个迭代器
function resume() {
var args = arguments //执行结果
process.nextTick(function() { //循坏迭代
var obj = idt.next(args).value
if (obj && isPromise(obj) //只能接受Primse对象
obj.then(
(res) => {
resume(null, res) //异步结束了 递归调用resume(执行结果) resume又会idt.next() 执行下一步
},
(err) => resume(err)
)
}, 0)
}
return resume
}
co.run = function(gen) {
co.wrap(gen)()
}
co.run(function * ($) {
// yield
//idt.next(args) args = [ null, 1]
const num1 = yield new Promise((resolve, reject) => {
setTimeout(()=>{
resolve(1)
}, 2E3);
});
//num2 = [null, 2]
const num2 = yield new Promise((resolve, reject) => {
setTimeout(()=>{
resolve(2)
}, 2E3);
});
console.log(num1[1] + num2[1]);
})
话说回来 这种不是promise对象就不继续执行了真的大丈夫? 而且process.nextTick 好像没什么意义
tj封装generator的co 库,不是很明白。Generator和Promise一样解决回调问题的 PS:这个有点标题党了,回答该问题只是对代码的探讨
@orangebook 该段代码涉及了闭包、 process.nextTick( )、递归、Generator、Promise等等。你如果还要说我标题党,我认了。
问题是,co 的源码不是这个样子的吧。。。
idt.next(args) 需要 try/catch
@gjc9620 arguments 不是执行结果 arguments是一个类似数组的对象,对应于传递给函数的参数。 例子:
function(arg1, arg2, arg3) {
var args = arguments
console.log(args[0]) // arg1
}
@magicdawn 为什么啊 在这里捕获不行么?
co.run(function * ($) {
try{
// yield
} catch(e) {}
})
co.run = function(gen) {
co.wrap(gen)()
}
这样一写,
var args = arguments
等于没用了…
@hyj1991 args对应的是resume(null, res)里面的参数,为什么没用呢?
这不是tj的co吧,这代码显然要var [err,result] = yield xxx()
这样来接收返回结果
@dlyt 是执行结果啊 所以num1 才会是[null ,1] 上一次异步执行的结果啊
@zxc122333 的确这么接收
@gjc9620 你这么说也可以,这个场景是的,但换个场景就不是了。 我上面说的也有问题。 args在resume()第一次执行的时候是{} 你能说执行结果是这个么?显然是不严谨的。 它就是一个类似数组的对象,用于传递给函数的参数。在这里用于获取resume函数的参数。而这个参数是用来传递结果的。
@gjc9620 process.nextTick 是有意义的,但这里滥用了。PS : Promise 看着蛋疼
@yyrdl process.nextTick 有何意义?
@gjc9620 避免伪异步造成异常 https://github.com/yyrdl/zco/blob/master/index.js#L160 160行这儿的注释
@yyrdl co.run(function * ($) {
$(anything) })
假如没有process.nextTick 这样写会 enerator is already running(当然。。) so 为什么要把resume 传进去。。 什么时候才会用到$()?