Promise是一种异步编程的比较优雅的解决方案
可以避免回调地狱
回调地狱:回调层层嵌套,函数作为参数,可读性和可维护性差
Promise可以理解为一个容器,里面保存着未来才会结束的事件
Promise对象的特点
-
对象的状态不受外界影响
Promise对象代表一个异步操作,其有三种状态:Pending、Fulfilled和Rejected。 且转变关系只有
Pending -> Fulfilled Pending -> Rejected -
一旦状态改变就不会再变,并且状态在任何时候都可以获得
Promise对象的状态一旦变为Fulfilled或Rejected会一直保持结果,称为"已定型(Resolved)"
与JS中的事件不同,事件一旦错过,就不可再监听到
Promise - Hello world!
var promise = new Promise(function(resolve, reject) {
// some code
const value = someAsyncFunctions();
// some code
if (/* 异步操作成功 */) {
resolve('I got the value of some async functions', value);
} else {
reject('Oh, some errors occured...')
}
});
以上通过一个Promise构造函数构造了一个Promise对象promise, Promise构造函数接受一个函数作为参数,该函数的两个参数resolve和reject是Javascript引擎实现的,不用关注实现细节
resolve是Promise内部回调执行成功后的处理函数,会将Promise对象的状态从Pending变为Resolved
reject是Promise内部回调执行成功后的处理函数,会将Promise对象的状态从Pending变为Rejected
console.log(promise)就会看到被Promise住的异步操作的结果:I got the value of some async functions 或 Oh, some errors occured...
Promise.then() || Promise.prototype.then()
官方解释:定义在原型对象Promise.prototype上的,作用是为Promise示例添加状态改变时的回调函数
通俗理解:Promise执行完了该干点啥,then()中的操作很可能是依赖于被Promise的异步操作的结果。
注意: then方法的第一个参数Resolved状态的回调函数,第二个参数(可选)是Rejected状态的回调函数。如下:
var promise = new Promise((resolve, reject) => {
// some code
const value = someAsyncFunctions();
// some code
if (/* 异步操作成功 */) {
resolve('I got the value of some async functions', value);
} else {
reject('Oh, some errors occured...')
}
}).then((success) => {
console.log('The Promise succeed, and it returns ', success) // 此处的success值即为第一个Promise的Resolved时的返回值
}, (fail) => {
console.log('The Promise failed, and it returns ', fail) // 此处的fail值同理
})
then方法返回的是一个Promise实例。 .then()可一直写下去,此即为链式调用。
Promise.catch() || Promise.prototype.catch() 本身不新鲜
只是Promise.prototype.then(null, rejection)的别名
写法稍有不同:
// 如果只是then(null, rejection)的话,错误处理函数即为rejection,如下:
new Promise((resolve, reject) => {
// some code
}).then(null, (rejection) => {
// do something when error occurs
})
// 这时候的rejection方法只是then方法的第二个参数
// 如果使用Promise.catch(),则catch方法是跟then方法同级的存在
new Promise((resolve, reject) => {
// some code
}).then((success) => {
// do something when Promise is success
}).catch((error) => {
console.log('Error! ', error);
})
// 注意: 这里catch能catch第一个Promise中发生的错误,也能catch then方法中发生的错误
// catch能捕获之前所有的Promise对象产生的错误,因为Promise对象的错误有“冒泡”的属性,会一直向后传递,直到被捕获
// 下面几种写法是等价的:
1.
var promise = new Promise((res, rej) => {
throw new Error('test');
});
promise.catch((error) => {
console.log('error'); // Error: test
});
2.
var promise = new Promise((res, rej) => {
try {
throw new Error('test');
} catch(err) {
reject(e);
}
});
promise.catch((error) => {
console.log(error);
});
3.
var promise = new Promise((res, rej) => {
reject(new Error('test'));
});
promise.catch((error) => {
console.log(error);
});
// reject方法作用就是抛出错误了吧。。。
一般来说,使用catch方法优于使用then方法的第二个参数捕获错误,因为catch可以捕获then方法中的错误
Promise.all() 将多个Promise对象包装成一个新的Promise实例
var p = Promise.all(p1, p2, p3)
p的状态由p1, p2, p3决定
- 只有p1, p2, p3的状态都变成Fullfilled,p的状态才变成Fullfilled,p1 p2 p3的返回值组成一个数组,传给p的回调函数
- p1, p2, p3中有一个被Rejected,p的状态就变成Rejected
只有p1, p2, p3都变成Fullfilled或有一个变成Rejected之后,才开始执行p