Bluebird-NodeJs的Promise

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的API文档了解更多。

时间: 2024-10-06 05:14:42

Bluebird-NodeJs的Promise的相关文章

Nodejs Promise的一点记录

项目需要,看了点nodejs,其中比较难理解的就是Promise了,记录一下学习bluebird提供的Promise实现. Promise.promisifyAll(obj)方法 作用:把对象的方法属性变成异步方法,会在函数加上后缀Async. 看下面的代码: var Promise = require('bluebird') var obj = { func1: function () { return 'hehe' }, func2: function () { return 'xix' }

深入理解jQuery、Angular、node中的Promise

最初遇到Promise是在jQuery中,在jQuery1.5版本中引入了Deferred Object,这个异步队列模块用于实现异步任务和回调函数的解耦.为ajax模块.队列模块.ready事件提供基础功能.在用jQuery操作DOM的时候对Promise的使用欲不够强烈,最近学习node和Angular,需要用js写业务逻辑和数据操作代码的时候这种场景需求就出来了.一般来说事件适合在交互场景中运用,因为用户的行为本来就是分散的,而promise这样的流程控制适合在后台逻辑中处理业务. //j

q.js实现nodejs顺序调用

nodejs的异步调用有时候是最让人头疼的,如何能是一些代码顺序的执行呢,这里和大家分享nodejs的promise 什么是promise promise一个标准,它描述了异步调用的返回结果,包括正确返回结果和错误处理.关于详细的说明文档可以参考Promises/A+.目前实现promise标准的模块有很多,如Q.bluebird和Deferred,下面我们以Q为例,介绍一下promise在nodejs中的使用方法. 我查找了关于promise的使用,其中最好用的就是q.js了,个人觉得.当然还

对promise的理解

前言 在公众号的开发里面用的const Promise = require('bluebird');const request = Promise.promisify(require('request'));这两句代码,之前一直没弄明白是啥意思,后来发现这是将callback函数重新用promise来实现. 什么是 promisify和promisifyall promisify 就是把带有 callback 函数,变成重新用 promise 来实现的一种技术方案,它能一劳永逸的解决:如何把函数

理解promise

原文地址: http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html 用Javascript的小伙伴们,是时候承认了,关于 promises 我们一直存在着问题.并非说 promises 本身有问题,Promises/A+ 是极好的. 就我过去数年观察大量 PouchDB API 以及其他 promise-heavy API 的使用者们与这些 API 的搏斗中我发现,最大的问题是: 大部分使用 promises 的小伙伴

promise之nodejsQ的详细用法总结

这里主要讲node.js中Q的各种用法及说明总结,不详细介绍promise及原理. * promise是解决JS中回调层次太深 代码难懂 改起来麻烦的问题. Q是nodeJs中实现promise的包之一,是nodeJs中比较常用的一个库. 在你的项目中安装Q的方法: npm install q -save 装好后我们就可以用Q来实现nodejs的promise了! Q实现promise的常用方法有7个,在不同情况下使用不同的方法,下面就一一来介绍: ------------低-----调----

使用ES6 +Promise组织异步代码

(1)为什么要使用promise这种设计模式,这种设计模式的好处是什么 解决 JavaScript 异步事件的传统方式是回调函数:调用一个方法,然后给它一个函数引用,当这个方法完结的时候执行这个函数引用. Javascript 中的神器--Promise Promise in js 回调函数真正的问题在于他剥夺了我们使用 return 和 throw 这些关键字的能力.而 Promise 很好地解决了这一切. 2015 年 6 月,ECMAScript 6 的正式版 终于发布了. ECMAScr

Node.js 101(2): Promise and async

--原文地址:http://blog.chrisyip.im/nodejs-101-package-promise-and-async 先回想一下 Sagase 的项目结构: lib/ cli.js sagase.js Gruntfile.js package.json 上一篇讲了 package.json,这一篇讲 lib/sagase.js. 由于代码比較长,就分开一节节地讲,完整的点开 GitHub 看吧. 'use strict'; 通知编译器进入 strict mode,基本的作用是让

Javascript 中的神器——Promise

Promise in js 回调函数真正的问题在于他剥夺了我们使用 return 和 throw 这些关键字的能力.而 Promise 很好地解决了这一切. 2015 年 6 月,ECMAScript 6 的正式版 终于发布了. ECMAScript 是 JavaScript 语言的国际标准,JavaScript 是 ECMAScript 的实现.ES6 的目标,是使得 JavaScript 语言可以用来编写大型的复杂的应用程序,成为企业级开发语言. 概念 ES6 原生提供了 Promise 对