1. 程式人生 > >promise執行順序總結

promise執行順序總結

面試遇到的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之後輸出
	    。。    等待十秒後代碼才算執行完畢
	*/