前几天一个朋友问:promise知道吗?
我也是集合了一下当前比较好的文章和案例给大家总结一下,下面开始。
Promise 是异步编程的一种解决方案,它由社区最早提出和实现,然后由ES6 将其写进了语言标准,统一了用法,原生提供了Promise 对象。
所谓Promise ,类似一个容器(假设一个大箱子,里面有很多你想的要的东西,只要你想的,哪里都有)。我理解的Promise就是一个对象,使用它主要可以获取异步操作的消息。在Promise对象上提供了一些 API,对各种异步操作都可进行处理。
Promise 对象特点:
(1)对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:pending
(进行中)、fulfilled/
resolve(已成功)和rejected
(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
(2)一旦状态发生改变,就不会再改变,无论任何时候都可以得到这个结果。Promise
对象状态的改变,有两种情况:从pending
变为fulfilled
和从pending
变为rejected
。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。
Promise 对象缺点:
第一,无法取消Promise
,一旦新建它就会立即执行,无法中途取消。第二,如果不设置回调函数,Promise
内部抛出的错误,不会反应到外部。第三,当处于pending
状态时,无法得知目前进展到哪一个阶段(刚开始pending过程还是即将结束pending的过程)。
基本用法:创建Promise对象
const promise = new Promise(function(resolve, reject) {
if (/* 成功响应异步操作完成 */){
resolve(success);
} else {
reject(error);
}
});
Promise构造函数接受一个函数作为参数,然后该函数所需要的两个参数分别是resolve和reject。
这两个参数由 JavaScript 引擎提供,不用自己部署。
resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),
在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;将success传递出去。
reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),
在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去;将error传递出去。
基本用法:创建Promise对象后.then方法回调处理
promise.then(function(value) {
// success
}, function(error) {
// error
});
then方法可以接受两个回调函数作为参数。
第一个回调函数是Promise对象的状态变为resolved时调用。
第二个回调函数是Promise对象的状态变为rejected时调用。
其中,第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数。
看下面例子,体会执行顺序
let promise = new Promise(function(resolve, reject) {
console.log('Promise');
resolve();
});
promise.then(function() {
console.log('resolved');
});
console.log('Hi');
// Promise
// Hi
// resolved
下面是一个使用Promise对象实现的 Ajax-get 例子
const getJSON = function(url) {
const promise = new Promise(function(resolve, reject){
const client = new XMLHttpRequest();
client.open("GET", url);
client.onreadystatechange = handler;
client.responseType = "json";
client.setRequestHeader("Accept", "application/json");
const handler = function() {
if (this.status === 200&&this.readyState == 4) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
client.send();
});
return promise;
};
getJSON("/posts.json").then(function(json) {
console.log('Contents: ' + json);
}, function(error) {
console.error('错误', error);
});
其实吧...你也可以自己封装一个promise-post请求...这里先不说了,有时间补上...
Promise.prototype.then() 个人觉得then 这知识点还好
Promise.prototype.catch() 个人比较烦catch这块,花点时间还得在搞一下
Promise.prototype.finally() 方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。不管Promise最后的状态,在执行完then
或catch
指定的回调函数以后,都会执行finally
方法指定的回调函数。finally
方法的回调函数不接受任何参数,这意味着没有办法知道,前面的 Promise 状态到底是fulfilled
还是rejected
。这表明,finally
方法里面的操作,应该是与状态无关的,不依赖于 Promise 的执行结果。
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
Promise.all() 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。Promise.all
方法接受一个数组作为参数,且都是 Promise 实例。(Promise.all
方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。)
// 生成一个Promise数组
const promises = [2, 3, 5, 7, 11, 13].map(function (i) {
return getJSON('/post/' + i + ".json");
});
Promise.all(promises).then(function (value) {
// ...
}).catch(function(error){
// ...
});
上面代码中,promises
是包含 6 个 Promise 实例的数组,只有这 6 个实例的状态都变成fulfilled
,或者其中有一个变为rejected
,才会调用Promise.all
方法后面的回调函数。
const a = aa();
const b = bb
.then(b);
const c = cc
.then(c);
Promise.all([
b,
c
])
.then(([bbb, ccc]) => pick(bbb,ccc));
上面代码中,b和c是两个异步操作,只有等到它们的结果都返回了,才会触发pick这个回调函数。
注意,如果作为参数的 Promise 实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法。
(这里我们没有定义)
看下面的例子
const p1 = new Promise((resolve, reject) => {
resolve('hello');
})
.then(result => result)
.catch(e => e);
const p2 = new Promise((resolve, reject) => {
throw new Error('报错了');
})
.then(result => result)
.catch(e => e);
Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));
// ["hello", Error: 报错了]
上面代码中,p1会resolved,p2首先会rejected,但是p2有自己的catch方法,
该方法返回的是一个新的 Promise 实例,p2指向的实际上是这个实例。
该实例执行完catch方法后,也会变成resolved,导致Promise.all()
方法参数里面的两个实例都会resolved,因此会调用then方法指定的回调函数,
而不会调用catch方法指定的回调函数。
如果p2没有自己的catch方法,就会调用Promise.all()的catch方法。
const p1 = new Promise((resolve, reject) => {
resolve('hello');
})
.then(result => result);
const p2 = new Promise((resolve, reject) => {
throw new Error('报错了');
})
.then(result => result);
Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));
// Error: 报错了
Promise.race() Promise.race
方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。
Promise.resolve() 有时需要将现有对象转为 Promise 对象,Promise.resolve
方法就起到这个作用。
Promise.reject() Promise.reject(reason)
方法也会返回一个新的 Promise 实例,该实例的状态为rejected
。