Promise和Async/Await用法整理

1.Promise
1.簡介
Promise,簡單來講就是一個容器,裏面保存着某個將來纔會結束的時間(一般是一個異步操做的結果)
Promise對象的基本語法:
new Promise((resolve,reject) => {前端

//.....

});數組

從語法上來講,Promise是一個對象,從它能夠獲取異步操做的消息。
基本語法:
let p = new Promise((resolve,reject) => {promise

//...
resolve('success')

});瀏覽器

p.then(result => {dom

console.log(result);//success

});異步

Promise對象特色和三個狀態:async

這裏寫圖片描述函數

例如:
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,就會報錯。這時候你就要想到是什麼錯誤。

結尾彩蛋

以上爲本期介紹,您能夠關注個人公衆號,關注更多前端知識,還有前端大羣一塊兒交流學習!

6581571394074_.pic.jpg

相關文章
相關標籤/搜索