摘要:以及模块之前都是返回的函数之后的都是返回在语言中,函数替换的是将多参数函数,替换成单参数的版本,且只接受回调函数作为参数。
Thunk以及CO模块
co4.0之前都是返回的thunk函数
之后的都是返回promise
thunk:在 JavaScript 语言中,Thunk 函数替换的是将多参数函数,替换成单参数的版本,且只接受回调函数作为参数。
</>复制代码
// 正常版本的readFile(多参数版本)
fs.readFile(fileName, callback);
// Thunk版本的readFile(单参数版本)
var readFileThunk = Thunk(fileName);
readFileThunk(callback);
var Thunk = function (fileName){
return function (callback){
return fs.readFile(fileName, callback);
};
};
生产环境中,可以使用thunkify将函数转换为thunk 函数
问题:
为什么node 里面大部分的callback都是第一个参数是err呢?
为什么要做thunk 转换呢?
在redux里面也有thunk middleware,这个thunk是什么意思呢?
CO 模块co的原理很简单,就是将传入的generator function 转换为一个thunk,并且转换后thunk 的generator的每个value值作为下一个状态的输入
</>复制代码
function co(fn) {
</>复制代码
var isGenFun = isGeneratorFunction(fn);
return function (done) {//返回的thunk函数,done 作为回调函数
var ctx = this;
// in toThunk() below we invoke co()
// with a generator, so optimize for
// this case
var gen = fn;
//gen function 转换为generator
if (isGenFun) {
var args = slice.call(arguments), len = args.length;
var hasCallback = len && "function" == typeof args[len - 1];
done = hasCallback ? args.pop() : error;
gen = fn.apply(this, args);
} else {
done = done || error;
}
//函数执行的时候就会执行next函数,进入函数体里面
next();
// #92
// wrap the callback in a setImmediate
// so that any of its errors aren"t caught by `co`
function exit(err, res) {
setImmediate(done.bind(ctx, err, res));
}
function next(err, res) {
var ret;
// multiple args
if (arguments.length > 2) res = slice.call(arguments, 1);
// error
if (err) {
try {
ret = gen.throw(err);
} catch (e) {
return exit(e);
}
}
// ok
if (!err) {
try {
ret = gen.next(res);
} catch (e) {
return exit(e);
}
}
// done
if (ret.done) return exit(null, ret.value);
// normalize
ret.value = toThunk(ret.value, ctx);
// run
if ("function" == typeof ret.value) {
var called = false;
try {
//比如执行yield readFile("test.json"), ret.value就是readFile函数,函数接受一个callback,callback调用next方法,讲readFile的结果传入了next函数
ret.value.call(ctx, function(){
//这里可以防止next函数被多次执行
if (called) return;
called = true;
next.apply(ctx, arguments);
});
} catch (e) {
setImmediate(function(){
if (called) return;
called = true;
next(e);
});
}
return;
}
// invalid
next(new Error("yield a function, promise, generator, array, or object"));
}
}
}
通过上面的co源码分析,可以看下面的例子
</>复制代码
</>复制代码
- co(function *() {
- var file = yield readFile("test.json");
-
- //这里的file是通过gen.next() 赋值的
- console.log(file);
-
- var ret = yield writeFile(file, "dest.json");
-
- console.log(ret);
- })
了解了这些基本概念后就可以进入koa的源码阅读了,具体的可以参考下一篇。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/78882.html
摘要:注是先前版本处理异步函数的方式,通过可以将异步函数封装成,传入普通参数后形成仅需要参数的偏函数,以此简化调用代码目前中的偏函数已经被无情地化了。 前几天研究了TJ的koa/co4.x和一系列koa依赖的源码,在知乎上做出了人生首次回答(而且我真得再也不想去知乎回答技术问题了_(:з」∠)_),因此把文字搬到这里。 ES2015 Generator/Yield 关于Generator...
摘要:经常游荡在的我总能发现许多好问题和好答案。尽管网络上有着各式各样的关于该主题的指导,但涉及到在各种情景下的最佳实践,或者较好实践的方面还是不够清晰。我寄希望于针对我这篇裹脚布式问题的回复可以改变这一现状。我感觉因此收益的绝对不止是我一个人。 经常游荡在 SO 的我总能发现许多好问题和好答案。它们的好不仅仅在于知识的价值,更可贵之处在于如何表达:如何提问/如何回答。不久前我在 SF...
摘要:也就是说,函数的执行,与普通函数一模一样,只要一行。表示函数里有异步操作,表示紧跟在后面的表达式需要等待结果。函数库约定,命令后面只能是函数或对象,而函数的命令后面,可以跟对象和原始类型的值数值字符串和布尔值,但这时等同于同步操作。 generator 特点 function* 可以使用yield返回多次 调用方法 使用next()执行generator代码,每次遇到yield...
阅读 669·2021-11-18 10:02
阅读 1136·2021-11-02 14:41
阅读 757·2021-09-03 10:29
阅读 1998·2021-08-23 09:42
阅读 2826·2021-08-12 13:31
阅读 1273·2019-08-30 15:54
阅读 2027·2019-08-30 13:09
阅读 1508·2019-08-30 10:55