Bluebird-NodeJs的Promise - 起点终站

我们应该感谢相遇,无论结局是喜是悲....
Bluebird-NodeJs的Promise
  • 首页 > 教程小结
  • 作者:起点终站
  • 2016年9月1日 16:18 星期四
  • 浏览:19707
  • 字号:
  • 评论:0
  • Promise是异步代码实现控制流的一种方式。这一方式可以让你的代码干净、可读并且健壮。
     

    比如,你用来异步处理文件事件的回调代码:

    fs.readFile('directory/file-to-read', function(err, file){
        if (error){
            //handle error
        } else {
            //do something with the file
        }
    });

    你以前可能听说过Node很快会陷入回调地狱,以上就是原因。作为一个node开发者你会遇到很多的异步代码,也就会遇到很多的回调(callback)。
     
    这些回调还是比较简单的。但是你会需要在一个动作完成之后继续做别的动作,因此回调会不断的嵌套。你会发现很快这些代码就很难阅读了,更别提维护了。比如:
     
    fs.readFile('directory/file-to-read', function(err, file){
        if (error){
            //handle error
        } else {
            //do something with the file
            fs.mkdir('directory/new-directory', function(err, file){
                if (error) {
                    //handle error
                } else {
                    //new directory has been made
                    fs.writeFile('directory/new-directory/message.txt', function(err, file){
                        if(error) {
                            // handle error
                        } else {
                            // File successfully created
                        }
                    });
                }
            });
        }
    });
    在上面的例子中我想要异步的读取一个文件,然后创建一个目录并创建一个文件。你可以看到这个简单的三步走的任务变成了多么丑陋的嵌套的代码,尤其是一旦你再在这些代码中添加逻辑控制的时候,代码更是不可想象丑陋。
     
     
     
    我们为什么要在node中使用Promise
     
    以上面对的代码作为例子,我们将探究如何用Promise解决上面说到的问题:
    fs.readFileAsync('directory/file-to-read')
        .then(function(fileData){
            return fs.mkdirAsync('directory/new-directory');
        })
        .then(function(){
            return fs.writeFileAsync('directory/new-directory/message.txt');
        })
    Promise给我们提供了一个更加清晰和健壮的方式编写异步代码。最开始的方法返回一个promise,这个promise上可以调用‘then’方法。‘then’之后还可以调用更多的‘then’。每个‘then’都可以访问上一个‘then’返回的信息。每一个‘then’方法返回的示例都可以再调用一个‘then’。这往往就是另一个异步的调用。
     
    Promise也让你更加容易的把代码分解到多个文件中。比如:
    function readFileandMakeDirectory(){
        return fs.readFileAsync('directory/file-to-read')
            .then(function(fileData){
                return fs.mkdirAsync('directory/new-directory');
            });
    }
     
    //The following will execute once the file has been read and a new directory has been made
    readFileandMakeDirectory()
        .then(function(){
            return fs.writeFileAsync('directory/new-directory/message.txt');
        })
    很容易创建返回promise的方法。当你需要把代码分解到不同的文件中的时候会非常有用。比如,你可能有一个路由读取一个文件,读取其内容,并且把文章内容以json的形式返回出来。你可以把代码分解成多个返回promise的组件
    //routes/index.js
    var router = require('express').Router();
    var getFileExcerpt = require('../utils/getFileExcerpt')
     
    router.get('/', function(){
        getFileExcerpt.then(function(fileExcerpt){
            res.json({message: fileExcerpt});
        });
    });
     
    module.exports = router;
     
    //utils/getFileExcerpt.js
     
    var Promise = require('bluebird');
    var fs = Promise.promisifyAll(require('fs'));
     
    module.exports = function getPost(){
        return fs.readFileAsync(file, 'utf8').then(function(content){
            return {
                excerpt: content.substr(0, 100)
            }
        });
    }

    以上代码也清楚的表明任何一个返回的‘then’后面可以再调用‘then’。
     
     
     
    处理错误
     
    使用promise处理错误非常简单。当执行一堆‘then’方法的过程中出现错误的时候Bluebird会找到最近的.catch方法执行。你可以在‘then’链中嵌入catch方法。上例可以改写为:
    fs.readFileAsync('directory/file-to-read')
        .then(function(fileData){
            return fs.mkdirAsync('directory/new-directory');
        })
        .then(function(){
            return fs.writeFileAsync('directory/new-directory/message.txt');
        })
        .catch(function(error){
            //do something with the error and handle it
        });

    你可以使用catch处理错误。
     
     
     
    但是我要用的模块不返回promise
     
    你会注意到上面的例子中使用了‘fs.writeFileAsync'和’fs.mkdirAsync’。如果你检查node的文档你会看到这些方法并不存在。FS不会返回promise。
     
    尽管如此,bluebird提供了一个非常有用的功能来promise化不返回promise的模块。比如,promise化fs模块,只需要简单地require bluebird模块和一个被promise化的fs模块。
     
    var Promise = require('bluebird');
    var fs = Promise.promisifyAll(require('fs'));
     
     
    创建你自己的Promise
     
    因为你可以promise化模块,所以你不会需要写很多的代码来创建promise。然后,即使如此知道如何创建也是很必要的。创建promise需要提供resolve和reject的回调方法。每一个都需要传对了:
    //myPromise.js
     
    var Promise = require('bluebird');
     
    module.exports = function(){
        return new Promise(function(resolve, reject){
            tradiationCallbackBasedThing(function(error, data){
                if (err) {
                    reject(err);
                } else {
                    resolve(data)
                }
            });
        });
    }
    这样就完成了promise化。接下来,你就可以使用这个技术把你想要promise化的都写成promise的形式。
     
     
     
    测试Promise
     
    当我测试服务端代码的时候,我最喜欢的框架是mocha和chai。需要注意,测试异步代码的时候你需要告诉mocha异步代码什么时候执行完成。否则,他只会继续执行下面的测试,这时就会出错。
     
    这个时候,只需要简单地调用mocha在it部分中提供的回调方法:
    it('should do something with some async code', function(done){
       readPost(__dirname + '/../fixtures/test-post.txt')
           .then(function(data){
               data.should.equal('some content inside the post');
               done();
           })
           .catch(done);
    });
    Promise非常有用,使用node编写异步代码的时候强烈建议你使用promise。

      您阅读这篇文章共花了:  
    本文作者:起点终站      文章标题: Bluebird-NodeJs的Promise
    本文地址:https://blog.hellozwh.com/?post=195
    版权声明:若无注明,本文皆为“起点终站”原创,转载请保留文章出处。
    • blogger
    返回顶部| 首页| 手气不错| 网站地图| sitemap| 装逼生成器| 站长介绍|

    Copyright © 2016-2019 起点终站 闽ICP备16011094号-1