nodejs之promise详解
来源:互联网 发布:业余网络作家收入多少 编辑:程序博客网 时间:2024/06/06 18:03
详细参考:http://liubin.org/promises-book/#__5
新建一个promise对象:
要想创建一个promise对象、可以使用new
来调用Promise
的构造器来进行实例化。
var promise = new Promise(function(resolve, reject) { // 异步处理 // 处理结束后、调用resolve 或 reject});
Instance Method
对通过new生成的promise对象为了设置其值在 resolve(成功) /reject(失败)时调用的回调函数可以使用promise.then()
实例方法。
promise.then(onFulfilled, onRejected)
- resolve(成功)时
onFulfilled
会被调用- reject(失败)时
onRejected
会被调用
onFulfilled
、onRejected
两个都为可选参数。
promise.then
成功和失败时都可以使用。另外在只想对异常进行处理时可以采用promise.then(undefined, onRejected)
这种方式,只指定reject时的回调函数即可。不过这种情况下promise.catch(onRejected)
应该是个更好的选择。
Static Method
像 Promise
这样的全局对象还拥有一些静态方法。
包括 Promise.all()
还有 Promise.resolve()
等在内,主要都是一些对Promise进行操作的辅助方法。
静态方法Promise.resolve(value)
可以认为是new Promise()
方法的快捷方式。
比如 Promise.resolve(42);
可以认为是以下代码的语法糖。
new Promise(function(resolve){ resolve(42);});
在这段代码中的 resolve(42);
会让这个promise对象立即进入确定(即resolved)状态,并将42
传递给后面then里所指定的onFulfilled
函数。
方法 Promise.resolve(value);
的返回值也是一个promise对象,所以我们可以像下面那样接着对其返回值进行.then
调用。
Promise.resolve(42).then(function(value){ console.log(value);});
Promise.all
接收一个 promise对象的数组作为参数,当这个数组里的所有promise对象全部变为resolve或reject状态的时候,它才会去调用 .then
方法。
数组里的方法会同时开始执行,而且每个promise的结果(resolve或reject时传递的参数值),和传递给Promise.all
的promise数组的顺序是一致的。
也就是说,这时候 .then
得到的promise数组的执行结果的顺序是固定的,即 [comment, people]。
接着我们来看看和 Promise.all
类似的对多个promise对象进行处理的 Promise.race
方法。
区别:
Promise.all
在接收到的所有的对象promise都变为 FulFilled 或者 Rejected 状态之后才会继续进行后面的处理,与之相对的是Promise.race
只要有一个promise对象进入 FulFilled 或者 Rejected 状态的话,就会继续进行后面的处理。
then(onFulfilled, onRejected)和catch的不同:
使用
promise.then(onFulfilled, onRejected)
的话在
onFulfilled
中发生异常的话,在onRejected
中是捕获不到这个异常的。
在
promise.then(onFulfilled).catch(onRejected)
的情况下then
中产生的异常能在.catch
中捕获
.then
和.catch
在本质上是没有区别的需要分场合使用。
Deferred和Promise的关系
简单来说,Deferred和Promise具有如下的关系。
Deferred 拥有 Promise
Deferred 具备对 Promise的状态进行操作的特权方法
所谓的能对Promise状态进行操作的特权方法,指的就是能对promise对象的状态进行resolve、reject等调用的方法,而通常的Promise的话只能在通过构造函数传递的方法之内对promise对象的状态进行操作。
function Deferred() { this.promise = new Promise(function (resolve, reject) { this._resolve = resolve; this._reject = reject; }.bind(this));}Deferred.prototype.resolve = function (value) { this._resolve.call(this.promise, value);};Deferred.prototype.reject = function (reason) { this._reject.call(this.promise, reason);};function getURL(URL) { var deferred = new Deferred(); var req = new XMLHttpRequest(); req.open('GET', URL, true); req.onload = function () { if (req.status === 200) { deferred.resolve(req.responseText); } else { deferred.reject(new Error(req.statusText)); } }; req.onerror = function () { deferred.reject(new Error(req.statusText)); }; req.send(); return deferred.promise;}// 运行示例var URL = "http://httpbin.org/get";getURL(URL).then(function onFulfilled(value){ console.log(value);}).catch(console.error.bind(console));
我们发现它们有如下不同。
Deferred 的话不需要将代码用Promise括起来
由于没有被嵌套在函数中,可以减少一层缩进
反过来没有Promise里的错误处理逻辑
在以下方面,它们则完成了同样的工作。
整体处理流程
调用
resolve
、reject
的时机
函数都返回了promise对象
由于Deferred包含了Promise,所以大体的流程还是差不多的,不过Deferred有用对Promise进行操作的特权方法,以及高度自由的对流程控制进行自由定制。
比如在Promise一般都会在构造函数中编写主要处理逻辑,对 resolve
、reject
方法的调用时机也基本是很确定的。
new Promise(function (resolve, reject){ // 在这里进行promise对象的状态确定});
而使用Deferred的话,并不需要将处理逻辑写成一大块代码,只需要先创建deferred对象,可以在任何时机对resolve
、reject
方法进行调用。
var deferred = new Deferred();// 可以在随意的时机对 `resolve`、`reject` 方法进行调用
换句话说,Promise代表了一个对象,这个对象的状态现在还不确定,但是未来一个时间点它的状态要么变为正常值(FulFilled),要么变为异常值(Rejected);而Deferred对象表示了一个处理还没有结束的这种事实,在它的处理结束的时候,可以通过Promise来取得处理结果。
如果各位读者还想深入了解一下Deferred的话,可以参考下面的这些资料。
Promise & Deferred objects in JavaScript Pt.1: Theory and Semantics.
Twisted 入门 — Twisted Intro
Promise anti patterns · petkaantonov/bluebird Wiki
Coming from jQuery · kriskowal/q Wiki
什么是 Promise.prototype.done ?
如果你使用过其他的Promise实现类库的话,可能见过用done
代替then
的例子。
这些类库都提供了 Promise.prototype.done
方法,使用起来也和then
一样,但是这个方法并不会返回promise对象。
使用Done例子
if (typeof Promise.prototype.done === 'undefined') { Promise.prototype.done = function (onFulfilled, onRejected) { this.then(onFulfilled, onRejected).catch(function (error) { setTimeout(function () { throw error; }, 0); }); };}var promise = Promise.resolve();promise.done(function () { JSON.parse('this is not json'); // => SyntaxError: JSON.parse});
从上面我们可以看出,两者之间有以下不同点。
done
并不返回promise对象也就是说,在done之后不能使用
catch
等方法组成方法链
done
中发生的异常会被直接抛给外面也就是说,不会进行Promise的错误处理(Error Handling)
由于done
不会返回promise对象,所以我们不难理解它只能出现在一个方法链的最后。
使用Promise进行顺序(sequence)处理
循环使用then调用的方法
使用for循环的方法
使用reduce的方法
分离出顺序处理函数的方法
另外提供promise扩展模块Q模块的方法大全文档:https://github.com/kriskowal/q/wiki/API-Reference
bluebird模块:http://bluebirdjs.com/docs/api-reference.html
- nodejs之promise详解
- nodejs之promise书写规范
- nodejs--promise之Q模块
- nodejs--promise之bluebird部分API
- Nodejs的Promise库
- NodeJS中的promise思考
- Bluebird-NodeJs的Promise
- nodejs之npm详解
- ES6基础之详解Promise基本用法
- [nodeJS篇]nodeJS之02-模块详解
- nodejs promise for q.js
- C++11之future,promise,packaged_task,async详解
- JQuery的Promise详解
- JQ promise详解
- JavaScript Promise对象详解
- 详解Promise对象
- JavaScript中Promise详解
- Promise对象详解
- dflist0614
- 虚拟机无法联网
- 解决android 对话框 宽度被限定在 65%的问题及背景透明问题
- redis学习日志二(windows操作系统redis的安装和启动)
- PHP JSON方式封装通信接口
- nodejs之promise详解
- 标准c++中string类函数介绍<转>
- ecshop开启debug模式的方法
- CSS(一)
- Reflect与jdk7引进的InvokeDynamic
- 高效的APP在线制作平台,让梦想轻松孵化器
- 题解——Leetcode 12. Integer to Roman 难度:Medium
- 微信小程序 循环执行 设定固定时间间隔
- Linux 用到的命令总结 持续更新