ES6 async函式(超級詳細、易懂)
技術標籤:ES6
下面是對 ES6 async函式的整理,希望可以幫助到有需要的小夥伴~
文章目錄
async函式是什麼
ECMAScript 2017規範引入了async函式,該函式的主要目的是簡化使用Promise非同步呼叫的操作,並對一組Promise執行某些操作。
Promise類似於結構化回撥
async、await類似於組合生成器和Promises。
await
操作符用於等待一個Promise 物件。它只能在非同步函式 async function 中使用
function resolveAfter2Seconds() {
return new Promise(resolve => {
setTimeout(()=>{
resolve('resolved');
},2000);
})
}
async function asyncCall() {
console. log("calling"); // calling
// 暫停當前asyncCall()函式的執行,等待Promise處理完成後再執行asyncCall()函式
var result = await resolveAfter2Seconds();
console.log(result); // resolved
}
asyncCall();
非同步函式宣告式
非同步函式宣告式用於定義一個返回Promise物件的非同步函式。
非同步函式是指通過事件迴圈非同步執行的函式,它會通過一個隱式的Promise返回其結果。
非同步函式的語法和結構與同步函式比較像。
async function name([param[, param[, ... param]ll) { statements }
- name:函式名稱
- param:要傳遞給函式的引數的名稱。
- statements:表示函式體語句。
非同步函式表示式
步函式表示式用於在表示式中定義非同步函式。
let name = async function([param1[, param2[ .., paramN]]]) { statements }
- name:表示函式名稱。
- pacam:要傳遞給函式的引數的名稱。
- statements:表示函式體語句。
非同步函式表示式與非同步函式語句宣告式的區別:
於非同步函式表示式可以省略函式名稱來建立一個匿名函式。
返回Promise物件
async函式返回一個Promise物件
async函式內部return語句返回的值,會成為then方法回撥函式的引數。
例項1:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-JPVf9Xvg-1608908797743)(es6/async1.png)]
例項2:
async function f() {
return "hello world";
}
// f().then(v=>console.log(v)); // hello world
// 等同於
f().then(
function (v) {
console.log(v); // hello world
}
)
// 上述非同步函式async function中沒有await表示式,因為非同步函式會先建立Promise物件,然後再執行
注意:
上述非同步函式async function中沒有await表示式,因為非同步函式會先建立Promise物件,然後再執行
await表示式
await表示式用於等待一個Promise物件,它只能在非同步函式中使用。
[return .value] = await expression;
-
expression:一個Promise物件或者任何要等待的值。
-
return…alue
- 如果等待的是Promise物件,返回Promise物件的處理結果(成功或失敗)。
- 如果等待的不是Promise 物件,則返回該值本身。
function createPromise(){
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve("執行成功");
},200);
});
}
async function myAsync() {
console.log("當前非同步函式被呼叫");
var result = await createPromise();
console.log("Promise物件執行的結果:" + result);
}
myAsync(); // 呼叫非同步函式
await處理錯誤
為了防止報錯,使用try…catch語句
function createPromise(){
return new Promise((resolve,reject) => {
setTimeout(() => {
reject("執行失敗");
},200);
});
}
async function myAsync() {
console.log("當前非同步函式被呼叫"); // 當前非同步函式被呼叫
try {
// 執行後會出錯的語句
var result = await createPromise();
} catch(e) {
// 提示錯誤的語句
console.log("Promise物件執行的結果:" + e); // Promise物件執行的結果:執行失敗
}
}
myAsync(); // 呼叫非同步函式
async函式執行一組Promise
一組Promise物件的執行順序只與async函式中await的順序有關。
let promise1 = new Promise((resolve,reject) => {
setTimeout(() => {
resolve("one");
},300);
});
let promise2 = new Promise((resolve,reject) => {
setTimeout(() => {
resolve("two");
},200);
});
let promise3 = new Promise((resolve,reject) => {
setTimeout(() => {
resolve("three");
},100);
});
async function myAsync() {
let result1 = await promise1;
console.log(result1);
let result2 = await promise2;
console.log(result2);
let result3 = await promise3;
console.log(result3);
}
myAsync();
// Promise物件執行的順序與設定的延遲時間沒有關係,Promise物件執行的順序只與async函式中的順序有關
注意事項
使用try…catch語句
await命令後面的Promise 物件,執行結果可能是rejected,有2種處理錯誤的方法
- try…catch語句
- Promise的catch語句
例項:
function fun() {
return new Promise((resolve,reject) => {
reject("執行失敗");
})
}
// try...catch處理錯誤
async function myAsync1() {
try {
await fun();
}catch (e) {
console.log(e);
}
}
myAsync1(); // 執行失敗
// catch處理錯誤
async function myAsync2() {
await fun().catch(function (err) {
console.log(err);
})
}
myAsync2(); // 執行失敗
多個await同時觸發
多個await表示式後面的非同步操作,如果不存在繼發關係,最好讓它們同時觸發。
let promise1 = new Promise((resolve,reject) => {
setTimeout(() => {
resolve("one");
},300);
});
let promise2 = new Promise((resolve,reject) => {
setTimeout(() => {
resolve("two");
},200);
});
let promise3 = new Promise((resolve,reject) => {
setTimeout(() => {
resolve("three");
},100);
});
// promise1,promise2,promise3依次獨立的非同步操作
/*async function myAsync() {
let result1 = await promise1;
console.log(result1);
let result2 = await promise2;
console.log(result2);
let result3 = await promise3;
console.log(result3);
}
myAsync();*/
// Promise物件執行的順序與設定的延遲時間沒有關係,Promise物件執行的順序只與async函式中的順序有關
// promise1,promise2,promise3同時執行非同步操作
async function myAsync3() {
let [result1,result2,result3] = await Promise.all([promise1,promise2,promise3]);
console.log(result1,result2,result3)
}
myAsync3(); // one two three
promise1,promise2,promise3是3個獨立的非同步操作(即互不依賴),被寫成繼發關係一個一個的進行非同步操作是比較耗時間的,可以讓promise1,promise2,promise3同時觸發,同時進行非同步操作(同時觸發的條件:promise1,promise2,promise3按順序執行)。
await表示式的限制
await表示式只能用在async函式之中,如果用在普通函式,就會報錯。
async function f1() {
let docs = [{},{},{}];
// 報錯
docs.forEach(function (doc) {
await db.post(doc); // SyntaxError: await is only valid in async function 翻譯:SyntaxError: await只在非同步函式中有效
})
}
Symbol
ECMAScript 6新增了第六種原始型別Symbol(符號)型別。
Symbol型別是唯一的並且是不可修改的,並且也可以用來作為Object 的 key 值。
Symbol型別的變數是通過呼叫Symbol()函式生成的:
Symbol([description])
- description:可選的字串。Symbol的描述,可用於除錯但不能訪問Symbol本身。
注意:
由於Symbol型別是原始型別,是不能通過new Symbol()來建立物件的。
例項:
/*
ES5 的 5種原始型別
* string - String
* number - Number
* string - String
* undefined - Undefined
* null - Null
ES6 新增一種原始型別
Symbol
*/
let num = 100; // new Number()
let str = "軟體學院"; // new String()
let boo = true;
/*
symbol型別是ES6新增的第六種原始型別
Symbol型別是唯一的並且是不可修
let symbol = Symbol()
原始型別是不能建立物件的
*/
let symbol = Symbol();
console.log(typeof symbol); // symbol 判斷原始型別必須使用typeof
let symbol2 = Symbol("xxx");
console.log(symbol2); // Symbol(xxx)
let symbol3 = Symbol(5);
console.log(symbol3); // Symbol(5)
// 修改變數的值,而不是修改型別,Symblo是不能轉為其它型別的
symbol3 = Symbol("yyy");
console.log(symbol3); // Symbol(yyy)
Symbol的注意事項
當使用Symbol值進行型別轉換時需要注意一些事情:
- 嘗試將一個symbol值轉換為一個number值時,會丟擲一個工ypeError錯誤。
- Object(symbol) == symnbol表示式的結果返回true。
- 阻止從一個symbol 值隱式地建立一個新的string型別的屬性名。
Symbol的方法
-
Symbol.for()方法
該方法會根據給定的鍵key,從symbol登錄檔中查詢指定的key。
- 如果找到了,則返回它。
- 如果沒有找到,新建一個與該鍵關聯的 symbol,並放入全域性symbol登錄檔中。
Symbol.for(key);
-
一個字串,作為symbol登錄檔中與某symbol關聯的鍵。
-
Symbol.for()方法與Symbol()的不同:
- 用Symbol.for()方法建立的的symbol會被放人一個全域性symbol登錄檔中
- 用Symbol()方法建立的的symbol不會被放人一個全域性symbol登錄檔中
登錄檔是一個典型的鍵值對key : value集合
舉例:
kye - 儲存的方式
value - 當前安裝的軟體
-
Symbol.keyFor()方法
該方法用於獲取symbol登錄檔中與某個symbol關聯的鍵。
Symbol.keyFor(sym);
- sym:儲存在symbol登錄檔中的某個symbol.
Symbol與for…in
Symbols 在 for…in迭代中不可列舉。
Object.getOwnPropertyNames()不會返回symbol物件的屬性,但是可以使用Object.getOwnPropertySymbols()得到它們.
var obj = {};
// 如果Symbol作為物件的屬性名,屬性名是不可列舉的
obj[Symbol("a")] = "a";
obj[Symbol.for("b")] = "b";
obj["c"] = "c";
obj.d = "d";
for (var i in obj) {
console.log(i); // c d 用Symbol作為物件的屬性名的a和b是沒有辦法被列舉的
}
end 結束啦~