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
constgetData=(name)=>{returnnewPromise((resolve,reject)=>{setTimeout(()=>{resolve('My name is '+name)},100)// 模拟异步获取数据})}construn=wrapAsync(function*(lastName){constdata1=yieldgetData('Jerry '+lastName)constdata2=yieldgetData('Lucy '+lastName)return[data1,data2]})run('Green').then((val)=>{console.log(val)// => [ 'My name is Jerry Green', 'My name is Lucy Green' ]})
有没有很熟悉?没错,如果你了解 co 这个库的话,你就知道, wrapAsync 就相当于 co.wrap
可以看到,上面我是直接利用了一个 递归 来实现的遍历,然后看下 co 内部是如何实现的,核心代码如下,总的来说,它不能进行处理基础数据,否则会报错,大概的原理和我的也差不多 😅😅
functionco(gen){varctx=this;varargs=slice.call(arguments,1);// we wrap everything in a promise to avoid promise chaining,// which leads to memory leak errors.// see https://github.com/tj/co/issues/180returnnewPromise(function(resolve,reject){if(typeofgen==="function")gen=gen.apply(ctx,args);if(!gen||typeofgen.next!=="function")returnresolve(gen);onFulfilled();/** * @param {Mixed} res * @return {Promise} * @api private */functiononFulfilled(res){varret;try{ret=gen.next(res);}catch(e){returnreject(e);}next(ret);returnnull;}/** * @param {Error} err * @return {Promise} * @api private */functiononRejected(err){varret;try{ret=gen.throw(err);}catch(e){returnreject(e);}next(ret);}/** * Get the next value in the generator, * return a promise. * * @param {Object} ret * @return {Promise} * @api private */functionnext(ret){if(ret.done)returnresolve(ret.value);varvalue=toPromise.call(ctx,ret.value);if(value&&isPromise(value))returnvalue.then(onFulfilled,onRejected);returnonRejected(newTypeError("You may only yield a function, promise, generator, array, or object, "+'but the following object was passed: "'+String(ret.value)+'"'));}});}functiontoPromise(obj){if(!obj)returnobj;if(isPromise(obj))returnobj;if(isGeneratorFunction(obj)||isGenerator(obj))returnco.call(this,obj);if('function'==typeofobj)returnthunkToPromise.call(this,obj);if(Array.isArray(obj))returnarrayToPromise.call(this,obj);if(isObject(obj))returnobjectToPromise.call(this,obj);returnobj;}
自己实现
先来了解下如何实现如下代码:
有没有很熟悉?没错,如果你了解 co 这个库的话,你就知道,
wrapAsync
就相当于 co.wrap一开始拿到这个题,自己也比较懵,因为自己很少使用 Generator,全都直接上手 async/await
大家都知道,
Generator
函数如果碰到yield
会暂停后面代码的执行,要调用next
方法才能向下执行,每次调用next
方法的时候,会返回一个对象,其中value
表示当前 yield 的返回值,done
,表示是否遍历完,如果是,则返回true
,否则返回false
。所以总的代码思路就是去循环判断这个done
是否为true
,然后对后面yield
的返回值做操作。这里就直接讲 如何实现一个类似 co 函数,因为 co.wrap 只不过是 co 的一个简单封装,这里将该函数取名为
rco
,以示区别。先来看下
rco
的基本使用:分析
实现
rco
上述代码说明
done = true
,表示已经遍历完value2Promise
上面说到了,我们会把 yield 后面的值全部转化为 promise,具体代码如下:
关于 thunk
使用
可以说是让用户自己控制何时 resolve
实现
关于收集对象中的 promise 值
使用
因为对象里的属性值也可能是 promise,所以我们需要去收集这些值,直到所有的 promise 都 resolve了之后又,才是真正 resolve 了该对象
实现
关于 rco.wrap
有了上面的基础,rco.wrap 只是基于上面的简单封装:
对比 co
可以看到,上面我是直接利用了一个 递归 来实现的遍历,然后看下 co 内部是如何实现的,核心代码如下,总的来说,它不能进行处理基础数据,否则会报错,大概的原理和我的也差不多 😅😅
最后
rco 已上传至 github,参见rco
如有不足,欢迎讨论 😊😊
The text was updated successfully, but these errors were encountered: