You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
exportdefaultfunctionwaterfall(tasks,callback){callback=once(callback||noop);if(!Array.isArray(tasks))returncallback(newError('First argument to waterfall must be an array of functions'));if(!tasks.length)returncallback();vartaskIndex=0;// 类似于自动执行器,和co模块功能相同,都是用于自动执行“async”后面的状态functionnextTask(args){vartask=wrapAsync(tasks[taskIndex++]);//对函数进行包装,判断函数是否是异步函数,同asyncifytask(...args,onlyOnce(next));// 如果args是空数组,就不会占据一个参数占位符,所以第一次调用时,参数只有一个onlyOnce(next)返回的函数}functionnext(err, ...args){if(err===false)return// https://github.com/caolan/async/issues/1064 false表达的是终止程序流程;对于更多的情况通常是传null/undefined,这里使用了一种技巧。<del>这里算是一个漏洞,不知道是有意为之还是疏忽大意,尽管发生概率不大</del>if(err||taskIndex===tasks.length){returncallback(err, ...args);}nextTask(args);}nextTask([]);}exportdefaultfunctiononce(fn){returnfunction(...args){if(fn===null)return;varcallFn=fn;fn=null;callFn.apply(this,args);};}exportdefaultfunctiononlyOnce(fn){returnfunction(...args){if(fn===null)thrownewError("Callback was already called.");varcallFn=fn;fn=null;callFn.apply(this,args);};}functionisAsync(fn){returnfn[Symbol.toStringTag]==='AsyncFunction';//这里没看懂,什么情况下会为true?? 已解决}functionwrapAsync(asyncFn){returnisAsync(asyncFn) ? asyncify(asyncFn) : asyncFn;}
waterfall
定义很简单,只用一个函数就解决了,比看
parallel
轻松多了。once
和onlyOnce
没看出来有什么区别,都只是为了保证fn
不为空;即使在被返回的函数里切断了fn
的关系,并不能使得下一次调用相同的fn
等于null
;我认为切断关系是为了尾调用优化
的机制。once
是为了保证fn
在所在的词法作用域(waterfall
)中只被调用一次,类似地,onlyOnce
也是为了保证fn
在所在的词法作用域(nextTask
)中只被调用一次。once
用于async库内部保证callback被安全调用一次;onlyOnce
用于外部调用async库内部的callback被安全调用一次,如果调用多次,把错误抛给用户。error===false
可以起到提前退出流程控制的作用,但是会使得程序挂起,因为callback
无法执行The text was updated successfully, but these errors were encountered: