Promise/async/await 是ES6裡面的新特性 個人理解如下:
1.建立Promise物件後會立即執行內部函式fn new Promise(fn);
1 new Promise(function(resolve, reject){ 2 console('new 完後馬上執行這個函式哦'); 3 });
2. Promise 可以透過resolve(r)返回結果 ,then函式接收結果 ,catch函式捕獲 throw e 異常, reject(e) 手動觸發catch呼叫
1 function test1(){ 2 return new Promise(function(resolve, reject){ 3 window.setTimeout(function(){ 4 try{ 5 //throw '丟擲的異常222'; //這裡丟擲的異常外部promise不能 直接 catch 到哦 需內部自己捕獲後呼叫 reject 傳遞到catch 6 7 console.log('test1.....'); 8 resolve('ooookkkk..'); //resolve 向下一個then傳遞結果 9 10 11 }catch(e){ 12 reject(e); //向catch 傳遞結果 13 } 14 15 },1000); 16 //throw '丟擲的異常111'; //這裡丟擲的異常能直接被.catch() 捕獲到哦 但是會使 setTimeout 裡面的 resolve不再呼叫了哦 17 }).then(function(r){ 18 console.log('呼叫 resolve 後會執行我哦'); 19 console.log(r); 20 21 }).catch(function(r){ 22 console.log('呼叫 reject 或throw e後 後會執行我哦'); 23 console.log(r); 24 }); 25 } 26 27 //let res1= test1(); // res1 是 Promise; 28 //console.log(res1);
3.async 關鍵字修飾函式後 函式的返回值就是Promise物件 如果函式就return a ; 那麼Promise物件的result=a;
1 async function test3_(n){ //async return 會封裝成 Promise 並把返回值 作為promise的result屬性內容\ 2 3 window.setTimeout(function(){ 4 console.log(n); 5 return n+100; 6 },1000); 7 if (n===3){ 8 throw '異常123'; 9 } 10 let a='返回string='+n; 11 return a; //實際返回Promise(result=a); 12 } 13 14 async function test3(){ 15 let a= await test3_(1); //這裡的返回值是 函式的實際return 返回值 並不會等待裡面的setTimeout完成 16 console.log(a); 17 let b= test3_(2); //這裡是 Promise 封裝 裡面封裝了 return 返回值 作為result欄位 18 console.log(b); 19 let c= test3_(3).catch(function(r){console.log(r);}); 20 console.log(c); 21 22 let d=new Promise(function(a,b){ 23 console.log('這樣也可以直接執行哦'); 24 return 'oookkkk'; //這裡的返回意義不大 25 }).then(function(r){ 26 console.log('成功了會執行我哦'); 27 }); 28 29 console.log(d); 30 } 31 //test3();
4.await 必須在async修飾的函式中使用
1 function test6(){ 2 3 } 4 function test7(){ 5 let z=await test6();//這種寫法是錯誤的 因為test6沒有返回Promise物件 6 }
5. await fn(); 中 fn 如果返回值不是Promise 物件, 則和普通函式呼叫無異
1 function test5(){ 2 3 console.log('111111'); 4 window.setTimeout(function(){ 5 console.log('222222'); 6 },1000); 7 return 33333; 8 } 9 async function test5_(){ 10 let a=await test5(); //這個時候和普通呼叫無異 因為沒有返回Promise物件 11 console.log(a); 12 } 13 test5_();
6. await fn(); 中 fn 如果返回Promise 物件 則等待Promise的result產生 後返回
1 function test8(){ 2 return new Promise(function(resolve, reject){ 3 resolve('成功返回'); //如果沒有then語句 result='成功返回'; 4 }).then(function(r){ 5 return '這裡優先作為結果'; //如果有這個返回 最終result='這裡優先作為結果'; 6 }); 7 } 8 9 async function test8_(){ 10 let z= await test8(); //如果 始終不呼叫 resolve 這裡將會一直等待下去 直到獲得result 11 console.log(z); 12 console.log('end...'); 13 } 14 15 test8_();
總結await ,async 和Promise 的關係 :
1. await 必須在 async修飾的函式中呼叫
2. async 修飾的函式會把結果包裝成Promise
3. await 等待的如果不是Promise 和普通呼叫無異
4.await 會一直等待Promise 的result 出現 並返回result
最後上全部的測試程式碼:
1 <html> 2 <head> 3 <title>Promise/async/await 理解</title> 4 </head> 5 <body> 6 <script type='text/javascript'> 7 new Promise(function(resolve, reject){ 8 console.log('new 完後馬上執行這個函式哦'); 9 }); 10 11 function test1(){ 12 return new Promise(function(resolve, reject){ 13 window.setTimeout(function(){ 14 try{ 15 //throw '丟擲的異常222'; //這裡丟擲的異常外部promise不能 直接 catch 到哦 需內部自己捕獲後呼叫 reject 傳遞到catch 16 17 console.log('test1.....'); 18 resolve('ooookkkk..'); //resolve 向下一個then傳遞結果 19 20 21 }catch(e){ 22 reject(e); //向catch 傳遞結果 23 } 24 25 },1000); 26 //throw '丟擲的異常111'; //這裡丟擲的異常能直接被.catch() 捕獲到哦 但是會使 setTimeout 裡面的 resolve不再呼叫了哦 27 }).then(function(r){ 28 console.log('呼叫 resolve 後會執行我哦'); 29 console.log(r); 30 31 }).catch(function(r){ 32 console.log('呼叫 reject 或throw e後 後會執行我哦'); 33 console.log(r); 34 }); 35 } 36 37 //let res1= test1(); // res1 是 Promise; 38 //console.log(res1); 39 40 41 42 function test2(n){ 43 return new Promise(function(resolve, reject){ 44 window.setTimeout(function(){ 45 console.log(n); 46 resolve(n+100); 47 },1000); 48 }); 49 //.then(function(r){ 50 // return 99999; 51 //}); 52 } 53 54 async function test2_(){ 55 //這裡加上await 後 會等待resolve的結果n+100 或then裡面的返回 如果不呼叫resolve 會一直等待 56 let a= await test2(1); 57 console.log(a); 58 let b= await test2(2); 59 console.log(b); 60 let c= await test2(3); 61 console.log(c); 62 } 63 64 //test2_(); 65 66 67 async function test3_(n){ //async return 會封裝成 Promise 並把返回值 作為promise的result屬性內容\ 68 69 window.setTimeout(function(){ 70 console.log(n); 71 return n+100; 72 },1000); 73 if (n===3){ 74 throw '異常123'; 75 } 76 let a='返回string='+n; 77 return a; //實際返回Promise(result=a); 78 } 79 80 async function test3(){ 81 let a= await test3_(1); //這裡的返回值是 函式的實際return 返回值 並不會等待裡面的setTimeout完成 82 console.log(a); 83 let b= test3_(2); //這裡是 Promise 封裝 裡面封裝了 return 返回值 作為result欄位 84 console.log(b); 85 let c= test3_(3).catch(function(r){console.log(r);}); 86 console.log(c); 87 88 let d=new Promise(function(a,b){ 89 console.log('這樣也可以直接執行哦'); 90 return 'oookkkk'; //這裡的返回意義不大 91 }).then(function(r){ 92 console.log('成功了會執行我哦'); 93 }); 94 95 console.log(d); 96 } 97 //test3(); 98 99 100 function test4(n){ 101 return new Promise(function(a, b){ 102 window.setTimeout(function(){ 103 a(n+1000); 104 },2000); 105 }); 106 } 107 108 async function test4_(n){ 109 let aa= await test4(n); 110 console.log(aa); 111 return aa; 112 } 113 114 async function test4___(){ 115 let a=test4_(1);//這種呼叫方式不等待函式內部的非同步結果 //返回Promise(result=aa); 如果await呼叫 則返回aa 116 console.log(a); 117 console.log('test4____'); 118 let b=await test4_(2);//這種呼叫等待函式內部的具體結果aa 119 } 120 //test4___(); 121 122 123 function test5(){ 124 125 console.log('111111'); 126 window.setTimeout(function(){ 127 console.log('222222'); 128 },1000); 129 return 33333; 130 } 131 async function test5_(){ 132 let a=await test5(); //這個時候和普通呼叫無異 因為沒有返回Promise物件 133 console.log(a); 134 } 135 //test5_(); 136 137 138 function test6(){ 139 140 } 141 function test7(){ 142 //let z=await test6();//這種寫法是錯誤的 因為test6沒有返回Promise物件 143 } 144 145 146 function test8(){ 147 return new Promise(function(resolve, reject){ 148 resolve('成功返回'); //如果沒有then語句 result='成功返回'; 149 }).then(function(r){ 150 return '這裡優先作為結果'; //如果有這個返回 最終result='這裡優先作為結果'; 151 }); 152 } 153 154 async function test8_(){ 155 let z= await test8(); //如果 始終不呼叫 resolve 這裡將會一直等待下去 直到獲得result 156 console.log(z); 157 console.log('end...'); 158 } 159 160 test8_(); 161 162 </script> 163 </body> 164 </html>