ฟังก์ชั่น Asyncเป็นคุณสมบัติใน ES2017สร้างรหัส async ให้ดูตรงกันโดยใช้สัญญา (รูปแบบเฉพาะของรหัส async) และawait
คำหลัก ให้สังเกตในตัวอย่างรหัสด้านล่างคำหลักที่async
อยู่ด้านหน้าของfunction
คำสำคัญที่แสดงถึงฟังก์ชัน async / await await
คำหลักจะไม่ทำงานโดยไม่ต้องอยู่ในฟังก์ชั่นก่อนการแก้ไขกับasync
คำหลัก เนื่องจากปัจจุบันไม่มีข้อยกเว้นสำหรับสิ่งนี้ซึ่งหมายความว่าจะไม่มีการรอระดับสูงสุด (ระดับสูงสุดกำลังรอหมายถึงการรอคอยนอกฟังก์ชั่นใด ๆ ) แม้ว่าจะมีข้อเสนอสำหรับระดับบนสุดawait
ES2017 เป็นที่ยอมรับ (เช่นสรุป) เป็นมาตรฐานสำหรับการใช้ JavaScript ในวันที่ 27 มิถุนายน 2017 Async รอคอยอาจจะทำงานอยู่แล้วในเบราว์เซอร์ของคุณ แต่ถ้าไม่คุณยังสามารถใช้ฟังก์ชั่นการใช้งานจาวาสคริปต์ transpiler เช่นBabelหรือtraceur Chrome 55 ได้รับการสนับสนุนอย่างเต็มที่จากฟังก์ชั่น async ดังนั้นหากคุณมีเบราว์เซอร์ใหม่คุณอาจลองใช้รหัสด้านล่าง
ดูตารางความเข้ากันได้ของ kangax es2017สำหรับความเข้ากันได้ของเบราว์เซอร์
นี่คือตัวอย่างของ async ที่รอฟังก์ชั่นที่เรียกว่าdoAsync
ซึ่งใช้เวลาสามวินาทีในการหยุดชั่วคราวและพิมพ์ความแตกต่างของเวลาหลังจากแต่ละหยุดจากเวลาเริ่มต้น:
function timeoutPromise (time) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(Date.now());
}, time)
})
}
function doSomethingAsync () {
return timeoutPromise(1000);
}
async function doAsync () {
var start = Date.now(), time;
console.log(0);
time = await doSomethingAsync();
console.log(time - start);
time = await doSomethingAsync();
console.log(time - start);
time = await doSomethingAsync();
console.log(time - start);
}
doAsync();
เมื่อคำสำคัญที่รออยู่ถูกวางไว้ก่อนหน้ามูลค่าสัญญา (ในกรณีนี้มูลค่าสัญญาคือค่าที่ส่งคืนโดยฟังก์ชัน doSomethingAsync) คำหลักที่รอคอยจะหยุดการเรียกใช้ฟังก์ชันชั่วคราว แต่จะไม่หยุดฟังก์ชันอื่นใดและจะดำเนินการต่อ รันโค้ดอื่น ๆ จนกว่าสัญญาจะคลี่คลาย หลังจากสัญญาได้รับการแก้ไขแล้วมันจะแกะมูลค่าของสัญญาและคุณสามารถนึกถึงการรอคอยและการแสดงออกของสัญญาซึ่งตอนนี้ถูกแทนที่ด้วยมูลค่าที่ยังไม่ได้เปิด
ดังนั้นเนื่องจากรอเพียงแค่หยุดรอแล้วปล่อยค่าออกมาก่อนที่จะดำเนินการส่วนที่เหลือของบรรทัดที่คุณสามารถใช้ในการลูปและฟังก์ชั่นการโทรภายในเช่นในตัวอย่างด้านล่างซึ่งรวบรวมความแตกต่างของเวลาที่รออยู่ในอาร์เรย์และพิมพ์อาร์เรย์
function timeoutPromise (time) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(Date.now());
}, time)
})
}
function doSomethingAsync () {
return timeoutPromise(1000);
}
// this calls each promise returning function one after the other
async function doAsync () {
var response = [];
var start = Date.now();
// each index is a promise returning function
var promiseFuncs= [doSomethingAsync, doSomethingAsync, doSomethingAsync];
for(var i = 0; i < promiseFuncs.length; ++i) {
var promiseFunc = promiseFuncs[i];
response.push(await promiseFunc() - start);
console.log(response);
}
// do something with response which is an array of values that were from resolved promises.
return response
}
doAsync().then(function (response) {
console.log(response)
})
ฟังก์ชัน async ส่งคืนสัญญาเพื่อให้คุณสามารถใช้เป็นสัญญากับการผูกมัดอย่างที่ฉันทำข้างบนหรือภายในฟังก์ชันรอคอยอีก async
ฟังก์ชั่นข้างต้นจะรอการตอบสนองแต่ละก่อนที่จะส่งคำขออื่นถ้าคุณต้องการที่จะส่งคำขอพร้อมกันคุณสามารถใช้Promise.all
// no change
function timeoutPromise (time) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(Date.now());
}, time)
})
}
// no change
function doSomethingAsync () {
return timeoutPromise(1000);
}
// this function calls the async promise returning functions all at around the same time
async function doAsync () {
var start = Date.now();
// we are now using promise all to await all promises to settle
var responses = await Promise.all([doSomethingAsync(), doSomethingAsync(), doSomethingAsync()]);
return responses.map(x=>x-start);
}
// no change
doAsync().then(function (response) {
console.log(response)
})
หากคำสัญญาอาจปฏิเสธคุณสามารถสรุปได้ในลอง catch หรือข้าม catch catch และปล่อยให้ข้อผิดพลาดแพร่กระจายไปยังฟังก์ชัน async / waitit catch call คุณควรระวังไม่ให้เกิดข้อผิดพลาดในสัญญาโดยเฉพาะใน Node.js ด้านล่างนี้เป็นตัวอย่างบางส่วนที่แสดงให้เห็นว่าข้อผิดพลาดทำงานอย่างไร
function timeoutReject (time) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
reject(new Error("OOPS well you got an error at TIMESTAMP: " + Date.now()));
}, time)
})
}
function doErrorAsync () {
return timeoutReject(1000);
}
var log = (...args)=>console.log(...args);
var logErr = (...args)=>console.error(...args);
async function unpropogatedError () {
// promise is not awaited or returned so it does not propogate the error
doErrorAsync();
return "finished unpropogatedError successfully";
}
unpropogatedError().then(log).catch(logErr)
async function handledError () {
var start = Date.now();
try {
console.log((await doErrorAsync()) - start);
console.log("past error");
} catch (e) {
console.log("in catch we handled the error");
}
return "finished handledError successfully";
}
handledError().then(log).catch(logErr)
// example of how error propogates to chained catch method
async function propogatedError () {
var start = Date.now();
var time = await doErrorAsync() - start;
console.log(time - start);
return "finished propogatedError successfully";
}
// this is what prints propogatedError's error.
propogatedError().then(log).catch(logErr)
หากคุณไปที่นี่คุณสามารถดูข้อเสนอที่เสร็จสิ้นแล้วสำหรับรุ่น ECMAScript ที่จะเกิดขึ้น
อีกทางเลือกหนึ่งสำหรับสิ่งนี้ที่สามารถใช้ได้กับ ES2015 (ES6) คือการใช้ฟังก์ชั่นพิเศษซึ่งจะหุ้มฟังก์ชั่นเครื่องกำเนิดไฟฟ้า ฟังก์ชันตัวสร้างมีคีย์เวิร์ดผลผลิตซึ่งอาจใช้ในการทำซ้ำคำสำคัญที่รออยู่พร้อมกับฟังก์ชันโดยรอบ คำหลักผลผลิตและฟังก์ชั่นเครื่องกำเนิดไฟฟ้ามีวัตถุประสงค์ทั่วไปมากขึ้นและสามารถทำสิ่งอื่น ๆ อีกมากมายแล้วเพียงแค่สิ่งที่ฟังก์ชั่น async รอทำ หากคุณต้องการเสื้อคลุมฟังก์ชั่นเครื่องกำเนิดไฟฟ้าที่สามารถนำมาใช้ในการทำซ้ำ async รอฉันจะตรวจสอบco.js โดยวิธีการที่ฟังก์ชั่นของ co เช่นเดียวกับ async กำลังรอฟังก์ชั่นคืนสัญญา จริง ๆ แล้ว ณ จุดนี้ความเข้ากันได้ของเบราว์เซอร์มีความคล้ายคลึงกันสำหรับทั้งฟังก์ชันตัวสร้างและฟังก์ชัน async ดังนั้นหากคุณต้องการให้ async รอฟังก์ชั่นการใช้งานคุณควรใช้ฟังก์ชั่น Async โดยไม่ต้องใช้ co.js
จริง ๆ แล้วการสนับสนุนเบราว์เซอร์ค่อนข้างดีสำหรับฟังก์ชั่น Async (จนถึงปี 2560) ในเบราว์เซอร์ปัจจุบันที่สำคัญทั้งหมด (Chrome, Safari และ Edge) ยกเว้น IE