利用promise写出更加优美的nodejs程序

什么是promise

promise一个标准,它描述了异步调用的返回结果,包括正确返回结果和错误处理。关于详细的说明文档能够参考Promises/A+。目前实现promise标准的模块有不少,如QbluebirdDeferred,下面咱们以Q为例,介绍一下promisenodejs中的使用方法。node

###将通常的异步调用的函数转换为promise风格的函数 好比通常状况下,咱们异步读取文件会写出下面的代码:git

fs.readFile("test.txt",function(err,data){
    if(!err){
        console.log(data);
    }else{
        console.error(err);
    }
});

咱们能够把fs.readFile函数封装为promise风格的函数,以下:github

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;
    });
}

这样咱们就能够这样调用这个方法了:promise

//then 的第一个参数是正确处理函数,第二个参数是错误处理函数
preadFile("test.txt").then(console.log,console.error);

能够看到这样调用更加直接明了。异步

###使用方法函数

  1. 各个回调函数顺序传递数据: 在nodejs中咱们回去数据时,时常遇回调函数的返回结果须要传递给下一个回调函数,到时很大的回调函数嵌套,promise 能够很轻松的在回调函数之间传递参数,看下面的例子:ui

    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,fun2fun3,若是须要调用不少函数,那么会造成很大的回调函数嵌套调用,致使代码看起来很丑陋,并且不容易维护,下面咱们改用promise重写这段代码:code

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
           });
    }
  1. 收集各个回调函数产生的数据:有时候咱们须要执行不少回调函数,然手把这个回调函数的数据一齐传递给一个函数处理,此时咱们能够使用allspread方法,参看以下代码:文档

    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' )
        });
  2. 统一处理错误:传统的回调函数方式使用的话,咱们须要在每个回调函数里判断是否有错误须要处理,这样会存在不少冗余代码,使用promise的话,能够使用done或者fail统一在一个函数中处理错误,如第一个例子同样,使用done方法的第二个参数处理错误。get

相关文章
相关标签/搜索