ES6 -- Promise对象
2017-08-02 09:16
239 查看
Promise是一种异步编程的解决方案,ES6提供原声的Promise,它比传统的解决方案,回调函数和事件,更加合理和强大。
Promise对象有以下两个特点:
1、对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending, resulved, rejected。只有异步操作的结果,可以决定是哪一种状态。
2、状态一旦改变,就不会再变化,并且任何时候都可以得到这个结果。
实用Promise对象,可以将异步操作用同步操作的流程表达出来,避免了层层嵌套的回调函数。
注意,函数resolve, reject由JS引擎提供,不用自己部署。
resolve函数的作用是将Promise对象的状态从“未完成”变为“成功”(即从 Pending 变为 Resolved),在异步调用成功的时候使用,并将异步操作的结果作为参数传递出去;reject函数将Promise对象的状态从“未完成”变为“失败”(即从 Pending 变为 Rejected),在异步操作失败时调用,并将异步操作报出的错误作为参数传递出去。
Promise实例生成以后,可以用then方法分别指定Resolved状态和Rejected状态的回调函数。
一个完整的例子:
timeout方法返回一个Promise实例。当Promise实例的状态变为Resolved,就会触发then方法绑定的回调函数。
另外,Promise对象在新建后就会立即执行。
下面是用Promise对象实现Ajax的例子:
reject函数的参数通常是Error对象的实例,表示抛出的错误;resolve函数的参数除了正常的值以外,还可能是另一个 Promise 实例:
上面代码中,p1和p2都是 Promise 的实例,
但是,重要的来了,p2的resolve方法将p1作为参数,即一个异步操作的结果是返回另一个异步操作。
这时,p1的状态就会传递给p2,也就是说,p1的状态决定了p2的状态。如果p1的状态是Pending,那么p2的回调函数就会等待p1的状态改变;如果p1的状态已经是Resolved或者Rejected,那么p2的回调函数将会立刻执行。
注意,调用resolve或reject并不会终结 Promise 的参数函数的执行。
then方法可以链式调用。
上面代码中,第一个then方法指定的回调函数,返回的是另一个Promise对象。这时,第二个then方法指定的回调函数,就会等待这个新的Promise对象状态发生变化。如果变为Resolved,就调用funcA,如果状态变为Rejected,就调用funcB。
另外,then方法指定的回调函数,如果运行中抛出错误,也会被catch方法捕获。
等价于:
Promise.resolve方法的参数分成四种情况。
1、参数是一个Promise实例
如果参数是Promise实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。
2、参数是一个thenable对象
thenable对象指的是具有then方法的对象,比如下面这个对象。
Promise.resolve方法会将这个对象转为Promise对象,然后就立即执行thenable对象的then方法。
3、参数不是具有then方法的对象,或根本就不是对象
如果参数是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve方法返回一个新的Promise对象,状态为Resolved。
4、不带有任何参数
Promise.resolve方法允许调用时不带参数,直接返回一个Resolved状态的Promise对象。
所以,如果希望得到一个Promise对象,比较方便的方法就是直接调用Promise.resolve方法。
需要注意的是,立即resolve的Promise对象,是在本轮“事件循环”(event loop)的结束时,而不是在下一轮“事件循环”的开始时。
Promise对象有以下两个特点:
1、对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending, resulved, rejected。只有异步操作的结果,可以决定是哪一种状态。
2、状态一旦改变,就不会再变化,并且任何时候都可以得到这个结果。
实用Promise对象,可以将异步操作用同步操作的流程表达出来,避免了层层嵌套的回调函数。
基本用法
var promise = new Promise(function(resolve, reject) { // ... some code if (/* 异步操作成功 */){ resolve(value); } else { reject(error); } });
注意,函数resolve, reject由JS引擎提供,不用自己部署。
resolve函数的作用是将Promise对象的状态从“未完成”变为“成功”(即从 Pending 变为 Resolved),在异步调用成功的时候使用,并将异步操作的结果作为参数传递出去;reject函数将Promise对象的状态从“未完成”变为“失败”(即从 Pending 变为 Rejected),在异步操作失败时调用,并将异步操作报出的错误作为参数传递出去。
promise.then(function(value) { // success }, function(error) { // failure });
Promise实例生成以后,可以用then方法分别指定Resolved状态和Rejected状态的回调函数。
一个完整的例子:
function timeout(ms) { return new Promise((resolve, reject) => { setTimeout(resolve, ms, 'done'); }); } timeout(100).then((value) => { console.log(value); });
timeout方法返回一个Promise实例。当Promise实例的状态变为Resolved,就会触发then方法绑定的回调函数。
另外,Promise对象在新建后就会立即执行。
下面是用Promise对象实现Ajax的例子:
var getJSON = function(url) { var promise = new Promise(function(resolve, reject){ var client = new XMLHttpRequest(); client.open("GET", url); client.onreadystatechange = handler; client.responseType = "json"; client.setRequestHeader("Accept", "application/json"); client.send(); function handler() { if (this.readyState !== 4) { return; } if (this.status === 200) { resolve(this.response); } else { reject(new Error(this.statusText)); } }; }); return promise; }; getJSON("/posts.json").then(function(json) { console.log('Contents: ' + json); }, function(error) { console.error('出错了', error); });
Promise“嵌套”
如果调用resolve函数和reject函数时带有参数,那么它们的参数会被传递给回调函数。reject函数的参数通常是Error对象的实例,表示抛出的错误;resolve函数的参数除了正常的值以外,还可能是另一个 Promise 实例:
var p1 = new Promise(function (resolve, reject) { // ... }); var p2 = new Promise(function (resolve, reject) { // ... resolve(p1); })
上面代码中,p1和p2都是 Promise 的实例,
但是,重要的来了,p2的resolve方法将p1作为参数,即一个异步操作的结果是返回另一个异步操作。
这时,p1的状态就会传递给p2,也就是说,p1的状态决定了p2的状态。如果p1的状态是Pending,那么p2的回调函数就会等待p1的状态改变;如果p1的状态已经是Resolved或者Rejected,那么p2的回调函数将会立刻执行。
注意,调用resolve或reject并不会终结 Promise 的参数函数的执行。
new Promise((resolve, reject) => { resolve(1); console.log(2); }).then(r => { console.log(r); }); // 2 // 1
Promise.prototype.then()
then方法的作用是为 Promise 实例添加状态改变时的回调函数。前面说过,then方法的第一个参数是Resolved状态的回调函数,第二个参数(可选)是Rejected状态的回调函数。then方法可以链式调用。
getJSON("/post/1.json").then(function(post) { return getJSON(post.commentURL); }).then(function funcA(comments) { console.log("Resolved: ", comments); }, function funcB(err){ console.log("Rejected: ", err); });
上面代码中,第一个then方法指定的回调函数,返回的是另一个Promise对象。这时,第二个then方法指定的回调函数,就会等待这个新的Promise对象状态发生变化。如果变为Resolved,就调用funcA,如果状态变为Rejected,就调用funcB。
Promise.prototype.catch()
Promise.prototype.catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。另外,then方法指定的回调函数,如果运行中抛出错误,也会被catch方法捕获。
Promise.resolve()
Promise.resolve()可以将现有对象转化为Promise对象。等价于:
Promise.resolve('foo') // 等价于 new Promise(resolve => resolve('foo'))
Promise.resolve方法的参数分成四种情况。
1、参数是一个Promise实例
如果参数是Promise实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。
2、参数是一个thenable对象
thenable对象指的是具有then方法的对象,比如下面这个对象。
let thenable = { then: function(resolve, reject) { resolve(42); } };
Promise.resolve方法会将这个对象转为Promise对象,然后就立即执行thenable对象的then方法。
3、参数不是具有then方法的对象,或根本就不是对象
如果参数是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve方法返回一个新的Promise对象,状态为Resolved。
var p = Promise.resolve('Hello'); p.then(function (s){ console.log(s) }); // Hello
4、不带有任何参数
Promise.resolve方法允许调用时不带参数,直接返回一个Resolved状态的Promise对象。
所以,如果希望得到一个Promise对象,比较方便的方法就是直接调用Promise.resolve方法。
需要注意的是,立即resolve的Promise对象,是在本轮“事件循环”(event loop)的结束时,而不是在下一轮“事件循环”的开始时。
Promise.reject()
Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected。相关文章推荐
- es6之Promise对象笔记
- es6 promise对象回调处理详解
- 自学-ES6篇-Promise对象
- 第十五节,Promise对象
- 在jQuery1.5中使用deferred对象 着放大镜看Promise
- 解决axios IE11 Promise对象未定义
- [轉]在jQuery1.5中使用deferred对象 - 拿着放大镜看Promise
- ES6中的promise对象
- Promise 对象
- bluebird.js - 让所有浏览器都支持 ES6 Promise 对象
- Promise对象实现异步编程
- Promise对象实现异步编程
- jQuery的deferred对象和promise对象
- ES6 的 Promise 对象
- ES6学习笔记(七)--Generator函数与Promise对象
- Promise对象
- AngularJS中的$http、$q服务和promise对象的联系
- promise对象学习
- JavaScript中对Promise对象的理解
- promise对象的简单用法