在写Node.js的过程中,连续的IO操作可能会导致“金字塔噩梦”,回调函数的多重嵌套让代码变的难以维护,利用CommonJs的Promise来封装异步函数,使用统一的链式API来摆脱多重回调的噩梦。
Node.js提供的非阻塞IO模型允许我们利用回调函数的方式处理IO操作,但是当需要连续的IO操作时,你的回调函数会多重嵌套,代码很不美观,而且不易维护,而且可能会有许多错误处理的重复代码,也就是所谓的“Pyramid of Doom”。
step1(function (value1) {
step2(value1, function(value2) {
step3(value2, function(value3) {
step4(value3, function(value4) {
// Do something with value4
});
});
});
});
这其实就是Node.js的Control flow的问题,对于这个问题,解决方案都许多,比如利用async,或者eventProxy等,不过本文的主题是利用CommonJs规范中对Promise来解决这个问题。
什么是Promise?
CommonJs的Promise规范有许多种,我们一般讨论的是Promise/A+规范,它定义了Promise的基本行为。
Promise是一个对象,它通常代表一个在未来可能完成的异步操作。这个操作可能成功也可能失败,所以一个Promise对象一般有3个状态:Pending,Fulfilled,Rejected。分别代表未完成、成功完成和操作失败。一旦Promise对象的状态从Pending变成Fulfilled或者Rejected任意一个,它的状态都没有办法再被改变。
一个Promise对象通常会有一个then方法,这个方法让我们可以去操作未来可能成功后返回的值或者是失败的原因。这个then方法是这样子的:
promise.then(onFulfilled, onRejected)
显而易见的是,then方法接受两个参数,它们通常是两个函数,一个是用来处理操作成功后的结果的,另一个是用来处理操作失败后的原因的,这两个函数的第一个参数分别是成功后的结果和失败的原因。如果传给then方法的不是一个函数,那么这个参数会被忽略。
then方法的返回值是一个Promise对象,这一个特点允许我们链式调用then来达到控制流程的效果。这里有许多细节上的问题,比如值的传递或者错误处理等。Promise的规范是这样定义的:
onFulfilled或者onRejected函数的返回值不是Promise对象,则该值将会作为下一个then方法中onFulfilled的第一个参数,如果返回值是一个Promise对象,怎么then方法的返回值就是该Promise对象
onFulfilled或者onRejected函数中如果有异常抛出,则该then方法的返回的Promise对象状态转为Rejected,如果该Promise对象调用then,则Error对象会作为onRejected函数的第一个参数
如果Promise状态变为Fulfilled而在then方法中没有提供onFulfilled函数,则then方法返回的Promise对象状态变为Fulfilled且成功的结果为上一个Promise的结果,Rejected同理。
补充一句,onFulfilled和onRejected都是异步执行的。
规范的实现:q
上面讲的是Promise的规范,而我们需要的是它的实现,q是一个对Promise/A+有着较好实现规范的库。
首先我们需要创建一个Promise对象,关于Promise对象创建的规范在Promise/B中,这里不做详细的解释,直接上代码。
function(flag){
var defer = q.defer();
fs.readFile("a.txt", function(err, data){
if(err) defer.reject(err);
else defer.resolve(data);
});
return defer.promise;
}
多数Promise的实现在Promise的创建上大同小异,通过创建一个具有promise属性的defer对象,如果成功获取到值则调用defer.resolve(value),如果失败,则调用defer.reject(reason),最后返回defer的promise属性即可。这个过程可以理解为调用defer.resolve将Promise的状态变成Fulfilled,调用defer.reject将Promise的状态变成Rejected。
在面对一系列连续的异步方法时,怎么利用Promise写出漂亮的代码呢?看下下面的例子。
promise0.then(function(result){
// dosomething
return result;
}).then(function(result) {
// dosomething
return promise1;
}).then(function(result) {
// dosomething
}).catch(function(ex) {
console.log(ex);
}).finally(function(){
console.log("final");
});
在上面的代码中,then方法只接受OnFulfilled,而catch方法实际上就是then(null, OnRejected),这样的话只要一系列异步方法只要始终是成功返回值的,那么代码就会瀑布式的向下运行,如果其中任意一个异步方法失败或者发生异常,那么根据CommonJs的Promise规范,将执行catch中的function。q还提供了finally方法,从字面上也很好理解,就是不论resolve还是reject,最终都会执行finally中的function。
看上去似乎不错,代码更以维护且美观了,那么如果希望并发呢?
q.all([promise0, promise1, promise2]).spread(function(val0, val1, val2){
console.log(arguments);
}).then(function(){
console.log("done");
}).catch(function(err){
console.log(err);
});
q也为并发提供了api,调用all方法并传递一个Promise数组即可继续使用then的链式风格。还有像q.nfbind等可以将Node.js的原生API转化成Promise来统一代码格式也是挺好的。更多api在这里就不一一详述了。
结论
本文主要介绍通过使用Promise来解决Node.js控制流问题,但Promise也可同样应用于前端,EMCAScript6已经提供了原生的API支持。需要指出的是Promise并不是唯一的解决方案,async也是一个很好的选择,并且提供更友好的并发控制API,不过我觉得Promise在封装具有异步方法的函数时更具优势。
好了,本文就先到这里了,希望对大家能够有所帮助。

Vue是一款流行的前端框架,在开发应用时经常会遇到各种各样的错误和问题。其中,Uncaught(inpromise)TypeError是常见的一种错误类型。在本篇文章中,我们将探讨它的产生原因和解决方法。什么是Uncaught(inpromise)TypeError?Uncaught(inpromise)TypeError错误通常出现在

在日常生活中,我们常常会遇到承诺与兑现之间的问题。无论是在个人关系中,还是在商业交易中,承诺的兑现都是建立信任的关键。然而,承诺的利与弊也常常会引起争议。本文将探讨承诺的利与弊,并给出一些建议,如何做到言出必行。承诺的利是显而易见的。首先,承诺可以建立信任。当一个人信守承诺时,他会让别人相信自己是一个可信赖的人。信任是人与人之间建立起的纽带,它可以让人们更加

Promise.resolve()详解,需要具体代码示例Promise是JavaScript中一种用于处理异步操作的机制。在实际开发中,经常需要处理一些需要按顺序执行的异步任务,而Promise.resolve()方法就是用来返回一个已经Fulfilled状态的Promise对象。Promise.resolve()是Promise类的一个静态方法,它接受一个

利用Promise对象,把普通函数改成返回Promise的形式,解决回调地狱的问题。明白Promise的成功失败调用逻辑,可以灵活的进行调整。理解核心知识,先用起来,慢慢整合吸收知识。

promise对象状态有:1、pending:初始状态,既不是成功,也不是失败状态;2、fulfilled:意味着操作成功完成;3、rejected:意味着操作失败。一个Promise对象一旦完成,就会从pending状态变为fulfilled或rejected状态,且不能再改变。Promise对象在JavaScript中被广泛使用,以处理如AJAX请求、定时操作等异步操作。

前端js学习中,让大家最难受的就是异步的问题,解决异步、回调地狱等问题时你必须得学会promise,对于多数前端程序员来说promise简直就是噩梦,本篇文章就是从通俗易懂的角度做为切入点,帮助大家轻松掌握promise

前端开发利器:Promise在解决异步问题中的作用与优势引言:在前端开发中,我们经常会遇到异步编程的问题。当我们需要同时执行多个异步操作或处理多个异步回调时,代码往往会变得复杂、难以维护。为了解决这样的问题,Promise应运而生。Promise是一种用于处理异步操作的编程模式,它提供了一种将异步操作以同步方式进行处理的能力,使得代码更加简洁和可读。本文将介


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

Atom编辑器mac版下载
最流行的的开源编辑器

Dreamweaver Mac版
视觉化网页开发工具

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。

EditPlus 中文破解版
体积小,语法高亮,不支持代码提示功能