Thunkify实现自执行函数
1.前言:
我们经常会有一些异步转同步的需求,比如链式执行就在很多插件中使用,而插件中的代码即可能是同步的也可能是异步的情况,所以我们需要提供一个函数能够:
- 顺序执行。
- 中间步骤控制。
- 异步/同步一致化处理。
这就是自执行函数的功能,自执行函数的作用是将generator函数转换为同步化顺序执行的函数。
2.实现代码:
function thunkify(fn) {
return function () {
let args = Array.from(arguments);
return function (callback) {
let called;
let proxyCallBack = function () {
if (called) {
return;
}
called = true;
callback.apply(null, Array.from(arguments));
}
let wholeArgs = [...args, proxyCallBack];
try {
return fn.apply(this, wholeArgs);
}
catch (err) {
callback(err);
}
}
}
}
function demo(arg,next){
console.log("demo"+arg+" done");
next();
}
let fnThunk = thunkify(demo);
//执行器生产函数
function * gen(){
yield fnThunk(1);
yield fnThunk(2);
}
//执行器
function run(g){
let genInstance = g();
let next = function(){
let res = genInstance.next();
if(!res || res.done) return;
res.value(next);
};
next();
}
run(gen);
//输出结果
//demo1 done
//demo2 done
上面代码很容易理解(当然你可能需要理解curry函数和generator函数),关键代码是这里:
let next = function(){
let res = genInstance.next();
if(!res || res.done) return;
res.value(next);
};
我们将generator函数的next封装到一个内部函数里面,然后传入res.value(这个其实就是
function demo(arg,next){
console.log("demo"+arg+" done");
next();
}
中的next参数),这样是否进入下一步就可以由被执行的函数在内部判断,把next放到异步函数resolve或者reject回调内部执行就可以将异步函数转化为(至少外部看起来)同步函数。通过这个处理我们就可以做出类似react-redux plugin或者 vue-router的beforeEach函数的功能来,是非常非常有用的函数概念。