Node.js里的异步调用是通过回调函数实现的,不管javascript的语言特性如何转变,至少在Node.js的native api里,肯定是回调函数。
比如读取文件
fs.readFile('/home/wqf/a.txt', function (err, data) { if (err) throw err; console.log(data); fs.readFile('/home/wqf/b.txt', function (err, data) { if (err) throw err; console.log(data); }); });
回调函数面临一个最大的问题就是callback hell,也就是多个异步操作有先后顺序时,会嵌套很多的回调函数。
为了防止这种情况,后来es6添加了yield关键字,我们看看它是如何运行的
function* asnycProc() { var data1 = yield readFile('/home/wqf/a.txt'); console.log(data1); var data2 = yield readFile('/home/wqf/b.txt'); console.log(data2); }
这个方法要做的事情和上面的回调写法没啥区别,实际上可以把每个yield语句以后的处理,当成yield语句所调用方法的回调。
但是毕竟后面的处理并不是一个方法,所以也不能用普通的方式进行回调,那么后面的处理是怎么执行的呢?
答案是next()
var g = asnycProc(); g.next(); g.next();
但是我们知道native api是通过回调方法执行的,默认不可能执行next()方法,那么就必须包装一下,通过包装一个执行next()的回调方法给native api用,但是next()方法是通过上面的形式执行的,我们没有办法直接把next()包装到回调方法里,必须得借助外力来执行这个next()。
这里有两种方法,一种是通过thunk函数,一种是通过promise对象。
关于thunk函数的介绍可以看这篇
http://www.ruanyifeng.com/blog/2015/05/thunk.html
目的就是把方法的其他参数跟回调方法参数分离,最终生成的方法就只有一个回调方法参数。
写个简单的thunk函数转换器就是
var Thunk = function(fn){ return function (){ var args = Array.prototype.slice.call(arguments); return function (callback){ args.push(callback); return fn.apply(this, args); } }; };
那么上面的readFile方法就可以写成
var readFile = Thunk(fs.readFile); readFile('/home/wqf/a.txt');这个方法返回了一个只能接收回调函数的方法
那么我们要做的事情就是下面这个语句返回的是native api里回调函数的参数data
yield readFile('/home/wqf/a.txt');
这又是怎么做到的呢?对于Generator方法,第一个yield语句的返回值是通过第二个next()方法传参回去的。
那么可以通过执行一下方法实现
var g = asnycProc(); var r1 = g.next(); r1.value(function(err, data){ if (err) throw err; var r2 = g.next(data); r2.value(function(err, data){ if (err) throw err; g.next(data); }); });
这里r1.value,就是yield readFile('/home/wqf/a.txt');语句中yield后面的值,也就是一个只可以接受回调方法参数的方法。然后再通过第二个g.next(data)方法把结果传了回去。
上面的这个执行函数顺序执行的处理是一样的,所以可以用递归来执行。
function run(fn) { var gen = fn(); function next(err, data) { var result = gen.next(data); if (result.done) return; result.value(next); } next(); } run(asnycProc);
接下来再看看promise的实现方法
把readFIle方法包装成promise对象
var readFile = function (fileName){ return new Promise(function (resolve, reject){ fs.readFile(fileName, function(error, data){ if (error) reject(error); resolve(data); }); }); };那么执行应该是这样的
var g = asnycProc(); g.next().value.then(function(data){ g.next(data).value.then(function(data){ g.next(data); }); })同样这个方法也可以用递归来实现
相关推荐
Node.js 应用程序是用 JavaScript 编写的,可以在 Mac OS X、Windows 和 Linux 上的 Node.js 运行时中运行而无需更改。 Node.js 应用程序旨在最大限度地提高吞吐量和效率,使用非阻塞 I/O 和异步事件。Node.js 应用...
Node.js 应用程序是用 JavaScript 编写的,可以在 Mac OS X、Windows 和 Linux 上的 Node.js 运行时中运行而无需更改。 Node.js 应用程序旨在最大限度地提高吞吐量和效率,使用非阻塞 I/O 和异步事件。Node.js 应用...
Node.js 应用程序是用 JavaScript 编写的,可以在 Mac OS X、Windows 和 Linux 上的 Node.js 运行时中运行而无需更改。 Node.js 应用程序旨在最大限度地提高吞吐量和效率,使用非阻塞 I/O 和异步事件。Node.js 应用...
Node.js 应用程序是用 JavaScript 编写的,可以在 Mac OS X、Windows 和 Linux 上的 Node.js 运行时中运行而无需更改。 Node.js 应用程序旨在最大限度地提高吞吐量和效率,使用非阻塞 I/O 和异步事件。Node.js 应用...
Full Stack Javascript - Learn Backbone.js, Node.js and MongoDB (APress 2015).epub Learning Node.js for Mobile Application Development (Packt 2015).pdf Microsoft Press Node.js for .NET Developers (2015...
StuQ分享专题《深入浅出js(Node.js)异步流程控制》完整版
Node.js 应用程序是用 JavaScript 编写的,可以在 Mac OS X、Windows 和 Linux 上的 Node.js 运行时中运行而无需更改。 Node.js 应用程序旨在最大限度地提高吞吐量和效率,使用非阻塞 I/O 和异步事件。Node.js 应用...
node.js的异步BDD和持续测试
node-firebird, 纯javascript和 node.js的异步 firebird 客户端 用于 Node.js.的纯 JavaScript firebird-客户端纯JavaScript和 node.js的异步 firebird 客户端。 firebird 论坛在Google网上论坛。社交
winston - 一个node.js多传输异步日志库
用于node.js的异步OpenCV 3.x API,包含以下示例:人脸检测,机器学习,深度神经网络,手势识别,对象跟踪,特征匹配,图像直方图
Node.js 应用程序是用 JavaScript 编写的,可以在 Mac OS X、Windows 和 Linux 上的 Node.js 运行时中运行而无需更改。 Node.js 应用程序旨在最大限度地提高吞吐量和效率,使用非阻塞 I/O 和异步事件。Node.js 应用...
Node.js 应用程序是用 JavaScript 编写的,可以在 Mac OS X、Windows 和 Linux 上的 Node.js 运行时中运行而无需更改。 Node.js 应用程序旨在最大限度地提高吞吐量和效率,使用非阻塞 I/O 和异步事件。Node.js 应用...
Node.js 应用程序是用 JavaScript 编写的,可以在 Mac OS X、Windows 和 Linux 上的 Node.js 运行时中运行而无需更改。 Node.js 应用程序旨在最大限度地提高吞吐量和效率,使用非阻塞 I/O 和异步事件。Node.js 应用...
Node.js 应用程序是用 JavaScript 编写的,可以在 Mac OS X、Windows 和 Linux 上的 Node.js 运行时中运行而无需更改。 Node.js 应用程序旨在最大限度地提高吞吐量和效率,使用非阻塞 I/O 和异步事件。Node.js 应用...
Node.js 应用程序是用 JavaScript 编写的,可以在 Mac OS X、Windows 和 Linux 上的 Node.js 运行时中运行而无需更改。 Node.js 应用程序旨在最大限度地提高吞吐量和效率,使用非阻塞 I/O 和异步事件。Node.js 应用...
Node.js 应用程序是用 JavaScript 编写的,可以在 Mac OS X、Windows 和 Linux 上的 Node.js 运行时中运行而无需更改。 Node.js 应用程序旨在最大限度地提高吞吐量和效率,使用非阻塞 I/O 和异步事件。Node.js 应用...
Electron Node.js 调用 dll动态库 以华旭金卡J10身份证阅读器为例,提示了dll动态库文件以及js源码: 文档说明:https://blog.csdn.net/qq_18944765/article/details/107913125?spm=1001.2014.3001.5501
Node.js 应用程序是用 JavaScript 编写的,可以在 Mac OS X、Windows 和 Linux 上的 Node.js 运行时中运行而无需更改。 Node.js 应用程序旨在最大限度地提高吞吐量和效率,使用非阻塞 I/O 和异步事件。Node.js 应用...
涵盖的主要内容有:Node.js的概念、应用场景、环境搭建和配置、异步编程;Node.js的模块概念及应用、Node.js的设计模式;HTTP简单服务的搭建、Node.js静态资源管理、文件处理、Cookie和Session实践、Crypto模块加密...