1、Promise对象概述
Promise对象用于表示一个异步操作的最终状态(完成或失败),以及其返回的值。它允许你为异步操作的成功和失败分别绑定相应的处理方法。 这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是返回一个能代表未来出现的结果的promise对象。
new Promise( function(resolve, reject) {...} /* executor */ );
一个 Promise
有以下几种状态:
-
pending: 初始状态,既不是成功,也不是失败状态。
-
fulfilled: 意味着操作成功完成。
-
rejected: 意味着操作失败。
当一种状态发生时,另一种状态就不会再发生了!,Promise对象为resolve和reject状态分别绑定一个回调函数,回调函数接收resolve和reject传回的参数。
2、常用API
then()方法是Promise实例的一个方法,第1个参数为Promise实例绑定当状态为操作成功(resolve)时的回调函数,第2个参数为Promise实例绑定当状态为操作失败(reject)时的回调函数。通常只写第一个参数。
catch()方法是Promise实例的一个方法,为Promise实例绑定当状态为操作失败(reject)时的回调函数,相当于 then(null,reject),应注意,当状态已经变成resolve,无法捕获抛出的错误;当存在链式操作时,应当把catch()方法放在最后。
Promise.all([,,,]);//将多个Promise实例封装成一个实例,只有当多个Promise实例的状态均为resolve时,最终状态才为resolve。
{ //高级用法 //多张图加载完成后再显示在页面上 function loadImg(src){ return new Promise((resolve,reject)=>{ let img = document.createElement('img'); img.src = src; img.onload = function(){ resolve(img); } img.onerror = function(){ reject(error); } }) } function showImgs(img){ imgs.forEach(function(img){ document.body.appendChild(img); }) } //将多个promise实例,包装成一个新的promise实例。 Promise.all([ loadImg('../20.jpg'), loadImg('../9.jpg'), loadImg('../p_05.jpg') ]).then(showImgs); }
Promise.race([,,,]);//先到先得,状态先变为resolve的实例先执行回调函数。
{ //先加载完成先显示 function loadImg(src){ return new Promise((resolve,reject)=>{ let img = document.createElement('img'); img.src = src; img.onload = function(){ resolve(img); } img.onerror = function(){ reject(error); } }) } function showImg(img){ let p = document.createElement('p'); p.appendChild(img); document.body.appendChild(p); } //谁先加载完成显示谁 Promise.race([ loadImg(''), loadImg(''), loadImg('') ]).then(showImg); }
定时器,事件,ajax等异步操作,会把该操作放到一个task queue里,需要等当前主线程的任务完成后,再读取任务队列(task queue)中的事件。而Promise对象的回调方法会放在主线程的最后,不会放到task中
setTimeout(function(){ console.log(1); }, 0) new Promise(function executor(resolve){ console.log(2); for(var i = 0; i < 1000; i++){ i = 9999 && resolve(); } console.log(3); }).then(function(){ console.log(4); }) console.log(5);
// setTimeout在定时时间后,将回调函数放到task队列中,在主线程执行完后,才会执行task队列
// 先输出2,3,Promise对象直接执行,then方法的函数放到主线程的最后
// 输出5
// 输出4,在主线程的最后执行
// 输出1