1.Promise
1.簡介
Promise,簡單來說就是一個容器,里面保存着某個未來才會結束的時間(通常是一個異步操作的結果)
Promise對象的基本語法:
new Promise((resolve,reject) => { //..... });
從語法上來說,Promise是一個對象,從它可以獲取異步操作的消息。
基本語法:
let p = new Promise((resolve,reject) => { //... resolve('success') }); p.then(result => { console.log(result);//success });
Promise對象特點和三個狀態:

例如:
let p = new Promise((resolve,reject) => { //... resolve('success'); console.log('after resolve'); reject('error'); }); p.then(result => { console.log(result); }); p.catch(result => { console.log(result); })
運行結果:
after resolve
success
resolve下面的語句其實是可以執行的,那么為什么reject的狀態信息在下面沒有接受到呢?這就是因為Promise對象的特點:狀態的凝固。new出一個Promise對象時,這個對象的起始狀態就是Pending狀態,在根據resolve或reject返回Fulfilled狀態/Rejected狀態。
2.

Then分別接受resolve和reject的信息,有三種參數形式,第三種比較“怪異”,只用來接收做reject處理。
eg:
let p = new Promise((resolve,reject) => { //... let random = Math.random();//小於1大於0 if(random > 0.4) { resolve('random > 0.4'); }else { reject('random <= 0.4'); } }); p.then(result => { console.log('resolve',result); }, result => { console.log('reject',result); });
3.鏈式調用
我們來執行一段代碼:
let p = new Promise((resolve,reject) => { reject('reject'); }); let resultP = p.then(null,result => { console.log(result); }); console.log(resultP);
結果:
Promise { <pending> }
reject
js的執行順序就是這樣,同步->異步->回調,在同步執行的時候,Promise對象還處於pending的狀態,也說明了這個then返回的是一個Promise對象。
而且必須在then里面給一個返回值,才能繼續調用,否則undefined。
eg:
let p = new Promise((resolve,reject) => { reject('error'); }); let resultP = p.then(null,result => { console.log(result); return 123; }); // console.log(resultP); resultP.then(tmp => { console.log(tmp); })
結果:
error
123
4.catch

eg:
let p = new Promise((resolve,reject) => { reject('error'); }); p.catch(result => { console.log(result); })
那這個catch的返回值是什么呢:
和上面then是一樣的。
5.Promise.resolve()

傳一個普通的對象:
// let p1 =Promise.resolve(123); let p1 =Promise.resolve({name:'xixi',age:'xxxx'}); p1.then(result => { console.log(result); });
如果是Promise對象呢,直接返回
let p = new Promise((resolve,reject) => { setTimeout(() => { resolve('success'); },500); }); let pp = Promise.resolve(p); pp.then(result => { console.log(result); }); console.log(pp == p);
結果:
true
success
6.Promise.reject()

eg:
let p = Promise.reject(123); console.log(p); p.then(result => { console.log(result); }).catch(result => { console.log('catch',result); })
結果:
Promise { <rejected> 123 }
catch 123
7.Promise.all()

eg:
let p1 = Promise.resolve(123); let p2 = Promise.resolve('hello'); let p3 = Promise.resolve('success'); Promise.all([p1,p2,p3]).then(result => { console.log(result); })
結果:
[ 123, 'hello', 'success' ]
成功之后就是數組類型,當所有狀態都是成功狀態才返回數組,只要其中有一個的對象是reject的,就返回reject的狀態值。
eg:
let p1 = Promise.resolve(123); let p2 = Promise.resolve('hello'); let p3 = Promise.resolve('success'); let p4 = Promise.reject('error'); // Promise.all([p1,p2,p3]).then(result => { // console.log(result); // }); Promise.all([p1,p2,p4]).then(result => { console.log(result); }).catch(result => { console.log(result); });
結果:
error
又一個eg:
//用sleep來模仿瀏覽器的AJAX請求 function sleep(wait) { return new Promise((res,rej) => { setTimeout(() => { res(wait); },wait); }); } let p1 = sleep(500); let p2 = sleep(500); let p3 = sleep(1000); Promise.all([p1,p2,p3]).then(result => { console.log(result); //..... //loading });
8.Promise.race

和all同樣接受多個對象,不同的是,race()接受的對象中,哪個對象返回的快就返回哪個對象,就如race直譯的賽跑這樣。如果對象其中有reject狀態的,必須catch捕捉到,如果返回的夠快,就返回這個狀態。race最終返回的只有一個值。
eg:
//用sleep來模仿瀏覽器的AJAX請求 function sleep(wait) { return new Promise((res,rej) => { setTimeout(() => { res(wait); },wait); }); } let p1 = sleep(500); let p0 = sleep(2000); Promise.race([p1,p0]).then(result => { console.log(result); }); let p2 = new Promise((resolve,reject) => { setTimeout(()=>{ reject('error'); },1000); }); Promise.race([p0,p2]).then(result => { console.log(result); }).catch(result => { console.log(result); });
500
error
9.異常處理

為什么說安靜,一個例子,Pormise內部的錯誤外界用try-catch捕捉不到
eg:
try { let p = new Promise((resolve, reject) => { throw new Error("I'm error"); // reject(new Error("I'm Error")); }); }catch(e) { console.log('catch',e); }
結果什么都沒打印。
但是拋出的錯誤可以通過catch來捕捉:
// try { let p = new Promise((resolve, reject) => { throw new Error("I'm error"); // reject(new Error("I'm Error")); }); // }catch(e) { // console.log('catch',e); // } p.catch(result => { console.log(result); });
這樣就捕捉到錯誤。所以:

2.Async-Await
1.簡介:


async和await在干什么,async用於申明一個function是異步的,而await可以認為是async wait的簡寫,等待一個異步方法執行完成。
2.基本語法

在Chrome里申明這樣一個函數,可以在控制台看到返回的其實就是一個Promise對象。
擴展需要了解的就是Chrome現在也支持asyncFunction,可以在Chrome控制台測試:
console.log(async function(){}.constructor);
ƒ AsyncFunction() { [native code] }
3.規則

如圖,await放在普通函數里是會報錯的。

eg:
async function demo() { let result = await Promise.resolve(123); console.log(result); } demo();
4.應用
Promise雖然一方面解決了callback的回調地獄,但是相對的把回調“縱向發展”了,形成了一個回調鏈。eg:
function sleep(wait) { return new Promise((res,rej) => { setTimeout(() => { res(wait); },wait); }); } /* let p1 = sleep(100); let p2 = sleep(200); let p =*/ sleep(100).then(result => { return sleep(result + 100); }).then(result02 => { return sleep(result02 + 100); }).then(result03 => { console.log(result03); })
控制台:
300
后面的結果都是依賴前面的結果。
改成async/await寫法就是:
async function demo() { let result01 = await sleep(100); //上一個await執行之后才會執行下一句 let result02 = await sleep(result01 + 100); let result03 = await sleep(result02 + 100); // console.log(result03); return result03; } demo().then(result => { console.log(result); });
因為async返回的也是promise對象,所以用then接受就行了。
結果:
300
需要注意的就是await是強制把異步變成了同步,這一句代碼執行完,才會執行下一句。
5.錯誤處理

如果是reject狀態,可以用try-catch捕捉
eg:
let p = new Promise((resolve,reject) => { setTimeout(() => { reject('error'); },1000); }); async function demo(params) { try { let result = await p; }catch(e) { console.log(e); } } demo();
結果:
error
這是基本的錯誤處理,但是當內部出現一些錯誤時,和上面Promise有點類似,demo()函數不會報錯,還是需要catch回調捕捉。這就是內部的錯誤被“靜默”處理了。
let p = new Promise((resolve,reject) => { setTimeout(() => { reject('error'); },1000); }); async function demo(params) { // try { let result = name; // }catch(e) { // console.log(e); // } } demo().catch((err) => { console.log(err); })
6.注意你的並行執行和循環
比如上面的例子:

如果這三個是你想異步發出的AJAX請求,在這段代碼里其實是同步的,第一個發出去才會發第二個,所以async/await需要謹慎使用。

現在有一些forEach或者map的循環里,比如在forEach里使用await,這時候的上下文就變成了array,而不是async function,就會報錯。這時候你就要想到是什么錯誤。
作者:Lawliet_ZMZ
鏈接:https://www.jianshu.com/p/fe0159f8beb4
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。