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); }); })同样这个方法也可以用递归来实现
相关推荐
JavaScript中的异步调用是编程中的重要概念,特别是在前端开发和Node.js环境中。异步调用主要用于处理耗时的操作,如网络请求、文件读写、定时任务等,以避免阻塞主线程,确保用户界面的流畅性。 在给定的问题中,...
在JavaScript的世界,异步编程是不可或缺的一部分,尤其是在Node.js环境中,由于其单线程特性,异步处理显得尤为重要。Express作为Node.js中最受欢迎的Web服务器框架之一,自然而然地需要面对和处理各种异步操作。...
此外,文档还讲述了JavaScript如何在服务器领域成为一股不可忽视的力量,通过Node.js的兴起,JavaScript成功地拓展到了非浏览器的环境中。 文档还提到了Paul Graham在2001年曾认为JavaScript不值得使用,但随后在其...
标题“native-node-module:从简单的根源开始,模块将不断发展”揭示了这个主题的核心,即探讨原生Node.js模块的发展历程和演变。 首先,让我们理解一下Node.js的基础。Node.js是一种基于Chrome V8引擎的JavaScript...
Browserify允许开发者将Node.js的CommonJS模块规范应用到浏览器端,它通过分析程序中的require调用,将所有依赖的模块打包到一个单独的JavaScript文件中。这意味着你可以在浏览器端使用类似于Node.js的模块加载方式...
3. **多线程支持**: SpiderMonkey允许在多线程环境中并行执行JavaScript,通过使用“worker”来支持异步计算,提高性能。 4. **API集成**: "js32.lib" 可能是SpiderMonkey的C/C++接口,使得开发者可以在原生应用中...
- **Node.js的兴起:** Node.js作为一个运行时环境,让JavaScript能够在服务器端执行,极大地扩展了JavaScript的应用范围。 - **JavaScript版本更新:** 介绍了ECMAScript标准的演进过程,强调了ES6(ECMAScript ...
随着时间的发展,JavaScript已经超越了浏览器环境,成为了一种全平台的编程语言,支持服务器端开发(Node.js)、移动应用、桌面应用、游戏开发等多种领域。 【JavaScript语法基础】 JavaScript语法基于ECMAScript...
随着JavaScript的发展与应用领域的扩展,特别是Node.js的出现,让JavaScript不仅局限于浏览器环境,更拓展到了服务器端。为了更好地管理和组织代码,模块化成为了JavaScript开发中不可或缺的一部分。在这个过程中,...
现代JavaScript已经发展出了Node.js平台,可以在服务器端进行开发。 【VBScript(Visual Basic Scripting Edition)】 VBScript是Microsoft开发的一种脚本语言,主要用于ASP(Active Server Pages)和Windows脚本...
随着Web技术的发展,JavaScript逐渐演变为一种全栈语言,不仅可以用于前端开发,也可以在服务器端通过Node.js运行。 1. **前端开发**:JavaScript在浏览器环境中运行,通过DOM(文档对象模型)操作HTML和CSS,实现...
如今,JavaScript 不仅是 Web 前端开发的核心技术之一,也在后端开发领域(如 Node.js)发挥着重要作用。 #### 二、JavaScript学习入门指南 ##### 1. DIV+CSS布局的重要性 - **概念理解**:DIV+CSS 是一种将网页...
10. **Node.js**:JavaScript也可以用于服务器端开发,Node.js是一个开放源代码、跨平台的JavaScript运行环境,它让开发者可以使用JavaScript编写服务器端代码。 11. **前端构建工具**:Webpack、Gulp、Grunt等工具...
随着时间的发展,它已经演变成一种全栈语言,不仅限于前端,还能在后端(如Node.js)和移动应用(如React Native)中使用。 1. **基础概念**: - 变量与数据类型:JavaScript支持动态类型,变量可以存储不同类型的...
2. **编程语言**:源码使用的编程语言可能有多种,如Python、JavaScript(Node.js)、Java或C#等。了解代码所用的语言是理解代码的第一步。 3. **网络请求与异步编程**:自动操作通常涉及网络请求,因此需要理解...
JavaScript在现代Web开发中的角色不断演变,从简单的客户端脚本语言发展到全栈开发工具。理解和掌握JavaScript,对于任何IT从业者来说,都是提升技术能力的关键步骤。通过深入学习和实践,开发者可以利用JavaScript...
9. **Node.js**:JavaScript也可以在服务器端运行,通过Node.js平台,它允许开发者使用JavaScript进行服务器编程,处理文件系统、网络请求等。 10. **前端框架**:JavaScript是React、Vue、Angular等现代前端框架的...
JavaScript提供了CommonJS(Node.js环境)和ES模块(浏览器环境)两种模块系统,用于组织代码和重用功能。 7. **AJAX和Fetch API**:用于在不刷新页面的情况下与服务器进行数据交换,是创建动态和交互式Web应用的...
- **调用中心**:Nginx + Node.js实现服务路由和负载均衡。 - **消息中心**:RabbitMQ处理异步通信和解耦。 - **日志中心**:Elasticsearch + Logstash + Kibana构建日志收集和分析平台。 - **监控中心**:...
在这个特定的项目中,我们可能会发现一系列与JavaScript相关的编程资源,因为“JavaScript”是给定的标签。JavaScript是一种广泛应用于网页和网络应用的编程语言,它允许实现动态内容,如交互式表单、动画效果以及...