promise執行順序總結
阿新 • • 發佈:2018-12-22
面試遇到的promise的執行順序問題,在這裡,總結下。之前部落格的賬號忘記了,新建了一個。
1、 const promise = new Promise((resolve, reject)=>{ console.log(1); resolve(); console.log(2); }) promise.then(()=>{ console.log(4); }) console.log(5); 執行結果是: 1,2,5,4 解釋:promise的建構函式是同步執行,promise.then中的函式是非同步執行。 2、 const promise = new Promise((resolve, reject) => { resolve('success1') reject('error') resolve('success2') }) promise .then((res) => { console.log('then: ', res) }) .catch((err) => { console.log('catch: ', err) }) 執行結果:then: success1 解釋:建構函式中的 resolve 或 reject 只有第一次執行有效,多次呼叫沒有任何 作用。promise 狀態一旦改變則不能再變。 promise 有 3 種狀 態: pending、fulfilled 或 rejected。 狀態改變只能是 pending->fulfilled 或者 pending-> rejected, 狀態一旦改變則不能再變。 3、const promise = new Promise((resolve, reject) => { setTimeout(() => { console.log('once') resolve('success') }, 1000) }) const start = Date.now() promise.then((res) => { console.log(res, Date.now() - start) }) promise.then((res) => { console.log(res, Date.now() - start) }) 執行結果:once success 1005 success 1007 解釋:promise 的 .then 或者 .catch 可以被呼叫多次,但這裡 Promise 建構函式 只執行一次。或者說 promise 內部狀態一經改變,並且有了一個值,那麼後續每 次呼叫 .then 或者 .catch 都會直接拿到該值。 4、console.log('start'); new Promise(function(resolve,reject){ setTimeout(function(){ //定時器模擬非同步 resolve('hello'); //修改promise狀態呼叫then中的第一個函式 },2000); }).then((value)=>{ console.log(value); //接收resolve傳來的值 return new Promise(function(resolve){ //該then()返回一個新的promise例項,後面可以繼續接then setTimeout(function(){ resolve('world'); //修改新promise的狀態,去呼叫then },3000) }) }).then((value)=>{ console.log(value); }) //輸出結果: /* 立即輸出 start 兩秒輸出 hello 再三秒 world */
5、上面我們在 then() 函式中返回的是一個新的promise,如果返回的不是一個新的promise會怎樣呢?依然是上面的程式碼,稍作修改。
console.log('start'); new Promise(function(resolve,reject){ setTimeout(function(){ resolve('hello'); },2000); }).then((value)=>{ console.log(value); (function(){ return new Promise(function(resolve){ setTimeout(function(){ resolve('world'); },3000) }) })(); return false; }).then((value)=>{ console.log(value); }) /* 結果: 立即輸出 start 兩秒輸出 hello 三秒輸出 false */ 根據上面的執行結果來看,如果在一個then()中沒有返回一個新的promise,則 return 什麼下一個then就接受什麼,在上面的例項程式碼中return的是false,下一個 then中接受到的value就是false,如果then中沒有return,則預設return的是 undefined.
6、then()中包含.then()的巢狀情況
then()的巢狀會先將內部的then()執行完畢再繼續執行外部的then();在多個then巢狀時建議將其展開,將then()放在同一級,這樣程式碼更清晰。
console.log('start'); new Promise((resolve,reject)=>{ setTimeout(function(){ console.log('step'); resolve(110); },1000) }) .then((value)=>{ return new Promise((resolve,reject)=>{ setTimeout(function(){ console.log('step1'); resolve(value); },1000) }) .then((value)=>{ console.log('step 1-1'); return value; }) .then((value)=>{ console.log('step 1-2'); return value; }) }) .then((value)=>{ console.log(value); console.log('step 2'); }) /* start step step1 step 1-1 step 1-2 110 step 2 */ //展開之後的程式碼 console.log('start'); new Promise((resolve,reject)=>{ setTimeout(function(){ console.log('step'); resolve(110); },1000) }) .then((value)=>{ return new Promise((resolve,reject)=>{ setTimeout(function(){ console.log('step1'); resolve(value); },1000) }) }) .then((value)=>{ console.log('step 1-1'); return value; }) .then((value)=>{ console.log('step 1-2'); return value; }) .then((value)=>{ console.log(value); console.log('step 2'); })
7、catch和then的連用
如果每一步都有可能出現錯誤,那麼就可能出現catch後面接上then的情況。上程式碼
new Promise((resolve,reject)=>{
resolve();
})
.then(value=>{
console.log('done 1');
throw new Error('done 1 error');
})
.catch(err=>{
console.log('錯誤資訊1:'+err);
})
.then(value=>{
console.log('done 2');
})
.catch(err=>{
console.log('錯誤資訊2:'+err);
})
/*
done 1
錯誤資訊1:Error: done 1 error
done 2
說明catch後面會繼續執行then,catch返回的也是一個promise例項
*/
new Promise((resolve,reject)=>{
resolve();
})
.then(value=>{
console.log('done 1');
throw new Error('done 1 error');
})
.catch(err=>{
console.log('錯誤資訊1:'+err);
throw new Error('catch error');
})
.then(value=>{
console.log('done 2');
})
.catch(err=>{
console.log('錯誤資訊2:'+err);
})
/*
done 1
錯誤資訊1:Error: done 1 error
錯誤資訊2:Error: catch error
如果在catch中也丟擲了錯誤,則後面的then的第一個函式不會執行,因為返回的
promise狀態已經為rejected了
8、Promise.all()
將多個Promise批量執行,所有的Promise都完畢之後返回一個新的Promise。
1、接收一個數組作為引數
2、陣列中可以是Promise例項,也可以是別的值,只有Promise會等待狀態的改變
3、所有子Promise完成,則該Promise完成,並且返回值是引數陣列中所有Promise實
例的結果組成的陣列
4、有任何一個Promise失敗,則該Promise失敗,返回值是第一個失敗的Promise的結果
console.log('here we go');
Promise.all([1,2,3])
.then(all=>{
console.log('1: ' + all);
return Promise.all([function(){
console.log('ooxx');
},'xxoo',false])
})
.then(all=>{
console.log('2: ' + all);
let p1 = new Promise(resolve=>{
setTimeout(function(){
resolve('I\'m p1');
},1500)
});
let p2 = new Promise(resolve=>{
setTimeout(function(){
resolve('I\'m p2');
},2000)
});
return Promise.all([p1,p2]);
})
.then(all=>{
console.log('3: '+all);
let p1 = new Promise((resolve,reject)=>{
setTimeout(function(){
resolve('P1');
},1000)
})
let p2 = new Promise((resolve,reject)=>{
setTimeout(function(){
reject('P2');
},3000)
})
let p3 = new Promise((resolve,reject)=>{
setTimeout(function(){
reject('P3');
},2000)
})
return Promise.all([p1,p2,p3]);
})
.then(all=>{
console.log('all: ' + all);
})
.catch(err=>{
console.log('Catch:' + err);
})
/*
here we go
1: 1,2,3
2: function(){
console.log('ooxx');
},xxoo,false
3: I'm p1,I'm p2
Catch:P3
證明了上面的四點。
*/
9、Promise.race()
和Promise.all()差不多,區別就是傳入的陣列中有一個Promise完成了則整個Promise完成了。
let p1 = new Promise(resolve=>{
setTimeout(function(){
resolve('p1');
},10000);
})
let p2 = new Promise(resolve=>{
setTimeout(function(){
resolve('p2');
},1000);
})
Promise.race([p1,p2])
.then((value)=>{
console.log(value);
})
/*
p1 1s之後輸出
。。 等待十秒後代碼才算執行完畢
*/