博客首页NodeJs分类

NodeJs中如何实现Promise?

发布时间:2016-05-17 18:57:43编辑:Mr.Co阅读(4575)

nodejs

什么是promise
promise一个标准,它描述了异步调用的返回结果,包括正确返回结果和错误处理。关于详细的说明文档可以参考Promises/A+。目前实现promise标准的模块有很多,如Q、bluebird和Deferred,下面我们以Q为例,介绍一下promise在 nodejs中的使用方法。

将一般的异步调用的函数转换为promise风格的函数

比如一般情况下,我们异步读取文件会写出下面的代码:
fs.readFile("test.txt",function(err,data){
    if(!err){
        console.log(data);
    }else{
        console.error(err);
    }
});
我们可以把fs.readFile函数封装为promise风格的函数,如下:
var preadFile = function(file){
    fs.readFile(file,function(err,data){
        var deferred = Q.defer();
        if(!err){
            deferred.resolve(data);
        }else{
            deferred.reject(err);
        }

        return deferred.promise;
    });
}
这样我们就可以这样调用这个方法了:
//then 的第一个参数是正确处理函数,第二个参数是错误处理函数
preadFile("test.txt").then(console.log,console.error);
可以看到这样调用更加直接明了。

使用方法
各个回调函数顺序传递数据: 在nodejs中我们回去数据时,时常遇回调函数的返回结果需要传递给下一个回调函数,到时很大的回调函数嵌套,promise 可以很轻松的在回调函数之间传递参数,看下面的例子:
var fun1 = function (data,cb) {
    cb(null,data+" fun1");
}

var fun2 = function (data,cb) {
    cb(null,data+" fun2");
}

var fun3 = function (data,cb) {
    cb(null,data+" fun3");
}

function main(data,cb){
    fun1(data,function(err,data){
        if(!err){
            fun2(data,function(err,data){
                if(!err){
                    fun3(data,cb);
                }else{
                    cb(err);
                }
            });
        }else{
            cb(err);
        }
    });
}
可以看到main函数为了得到数据,需要嵌套调用fun1,fun2和fun3,如果需要调用很多函数,那么会形成很大的回调函数嵌套调用,导致代码看起来很丑陋,而且不容易维护,下面我们改用promise重写这段代码:
var Q = require("q");
var fun1 = function (data) {
    var deferred = Q.defer();
    deferred.resolve(data+" fun1");
    return deferred.promise;
}

var fun2 = function (data) {
    var deferred = Q.defer();
    deferred.resolve(data+" fun2");
    return deferred.promise;
}

var fun3 = function (data) {
    var deferred = Q.defer();
    deferred.resolve(data+" fun3");
    return deferred.promise;
}

function main(data,cb){
   fun1("test")
       .then(fun2)
       .then(fun3)
       .done(function(data){
           cb(null,data);//ok 获得的最终数据为 --->"test fun1 fun2 fun3"
       },function(err){
           cb(err);//failed
       });
}
收集各个回调函数产生的数据:有时候我们需要执行很多回调函数,然手把这个回调函数的数据一齐传递给一个函数处理,此时我们可以使用all和spread方法,参看如下代码:
var Q = require("q");
var fun1 = function (data) {
    var deferred = Q.defer();
    deferred.resolve(data+" fun1");
    return deferred.promise;
}

var fun2 = function (data) {
    var deferred = Q.defer();
    deferred.resolve(data+" fun2");
    return deferred.promise;
}

var fun3 = function (data) {
    var deferred = Q.defer();
    deferred.resolve(data+" fun3");
    return deferred.promise;
}

Q.all([
    fun2("test1"),fun3("test2"),fun4("test3")
    ]).spread(function(){
        console.log(arguments);//获得的参数为('test1 fun1', 'test2 fun2', 'test3 fun3' )
    });
统一处理错误:传统的回调函数方式使用的话,我们需要在每一个回调函数里判断是否有错误需要处理,这样会存在很多冗余代码,使用promise的话,可以使用done或者fail统一在一个函数中处理错误,如第一个例子一样,使用done方法的第二个参数处理错误。
原文:http://my.oschina.net/sundq/blog/227410?utm_source=tuicool&utm_medium=referral

转载请注明出自:http://www.mrco.cn/article/573af927540a56dc56d683ff.html

最新评论(0)

    我要评论

    *
    *
    *
    *
    *
    *
    验证码