Promise 是异步编程的解决方案,它可以很方便的处理异步事件。一个 Promise 实例包含一个异步操作,这项异步操作只有三种状态,pending 初始状态,既不是成功,也不是失败状态,Resolved 成功完成,Rejected 异步操作失败。
Promise 的状态不受外界影响而且一旦状态改变,就不会再改变。
创建 Promise
要创建 Promise 实例要用到 Promise 类,它接受一个函数作为参数,函数接受两个参数,这两个参数也是函数,一个是当异步成功执行时需要调用的函数,一个是失败时调用的函数。
创建 Promise 实例的参数函数,将会立即执行。
function getData(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onload = () => resolve(xhr.responseText);
// 将状态变为 Resolved 并传入获取到的数据
xhr.onerror = () => reject(xhr.statusText);
// 将状态变为 Rejected 并传入错误信息
xhr.send();
})
}
//调用 getData 将返回一个 Promise 实例
Promise 的原型方法
Promise 一共有三个原型方法,then, catch 和 finally。
then
then 方法接受两个函数参数,一个是成功时候执行,一个是失败时执行。
而且then方法将会返回一个新的 Promise 实例,这就代表可以进行链式操作。
立即调用resolve的Promise,它then方法的参数函数会放到本次事件循环末尾。
let p1 = getData('http://www.a.cn')
let onFulfilled = data => console.log(data)
let onRejected = err => console.log(err)
p1.then(onFulfilled, onRejected)
// 当成功时将会调用第一个回调函数,并把 resolve 传入的参数再全部传入 onFulfilled 中
// 当成功时将会调用第二个回调函数,并把 resolve 传入的参数再全部传入 onRejected 中
let p2 = getData('http://www.a.cn')
p2.then(url => getData(url))
.then(data => console.log(data)) // 链式操作
// ------------------
let p = new Promise(resolve => {
console.log(1)
resolve(3)
})
console.log(2)
setTimeout(() => console.log(4))
p.then(num => console.log(num))
// 打印顺序是 1 2 3 4
catch
catch 方法接受一个函数参数onRejected,catch其实就是then的第二个参数。
catch方法一般放在最后面,前面then方法,将会冒泡到它这里。
catch 返回的还是一个 Promise 对象。不过catch捕获不了后面的then方法抛出的错误当然catch方法中也可以抛出错误。
let p3 = getData('http://a.com')
p3.then(data => console.log(data))
.then(() => throw new Error('error')) // 抛出错误
.then(() => console.log(1))
.catch(err => console.log(err))
// catch 将会捕获上面的错误,而且第三个 then 方法会被跳过
Promise 中未捕获的错误不会终止脚本执行而是打印一个未捕获 promise 错误提示。
finally
finally 方法接受一个函数参数onFinally。它不管 Promise 对象最后状态如何,都会执行的操作。finally方法的回调函数不接受任何参数。
它返回一个设置了 finally 回调函数的Promise对象。
Promise.prototype.finally = function (callback) {
let P = this.constructor;
return this.then(
value => P.resolve(callback()).then(() => value),
reason => P.resolve(callback()).then(() => { throw reason })
);
};
// finally 相当于返回一个已经带两个参数的 then 方法
Promise 方法
Promise 一共有 4 个静态方法。分别是all, race, resolve 和 reject。
resolve
resolve 接受一个参数,返回一个状态由给定value决定的Promise对象。
如果参数是 Promise 对象则直接返回。
如果参数是thenable(即,带有then方法的对象),then 方法会作为Promise的参数,立即执行。
如果是其他值返回一个新的 Promise 对象,状态为resolved,该value传递给对应的then方法。
Promise.resolve(1).then(num => {
console.log(num)
});
reject
reject 方法接受一个参数,返回一个状态为失败的Promise对象,并将给定的失败信息传递给对应的处理方法。
Promise.reject('error');
// 等同于
new Promise((resolve, reject) => reject('error'))
all
all 方法接受具有 iterable 接口 参数。
这个方法返回一个新的promise对象,该promise对象在iterable参数对象里所有的promise对象都成功的时候才会触发成功,一旦有任何一个iterable里面的promise对象失败则立即触发该promise对象的失败。
这个新的promise对象在触发成功状态以后,会把一个包含iterable里所有promise返回值的数组作为成功回调的返回值,顺序跟iterable的顺序保持一致
如果这个新的promise对象触发了失败状态,它会把iterable里第一个触发失败的promise对象的错误信息作为它的失败错误信息。
参数中的每个项目都是一个 Promise 对象,如果不是则用 resolve 方法转换成 Promise 对象。
race
race 方法和 all 方法一样,但是当iterable参数里的任意一个子 Promise 被成功或失败后,返回的 Promise 对象的状态就变成这个子 Promise 对象的状态,它的值或错误信息也会传递给返回 Promise 对象的回调函数。
Promise 的属性
Promise 一共有两个属性,length 和 prototype。
length属性,其值总是为 1 (构造器参数的数目)。