Ðелаем аÑÐ¸Ð½Ñ Ñонное пÑогÑаммиÑование более пÑоÑÑÑм Ñ async и await
Ð ECMAScript веÑÑии 2017 поÑвилиÑÑ async functions и клÑÑевое Ñлово await (ECMAScript Next support in Mozilla). Ðа Ñамом деле, ÑÑи ÑÑнкÑии еÑÑÑ Ð½Ð¸Ñего иное как ÑинÑакÑиÑеÑкий ÑаÑ
Ð°Ñ Ð½Ð°Ð´ Promises и Generator functions (ts39). С иÑ
помоÑÑÑ Ð»ÐµÐ³Ñе пиÑаÑÑ Ð¸ ÑиÑаÑÑ Ð°ÑинÑ
ÑоннÑй код, Ð²ÐµÐ´Ñ Ð¾Ð½Ð¸ позволÑÑÑ Ð¸ÑполÑзоваÑÑ Ð¿ÑивÑÑнÑй ÑинÑ
ÑоннÑй ÑÑÐ¸Ð»Ñ Ð½Ð°Ð¿Ð¸ÑаниÑ. Ð ÑÑой ÑÑаÑÑе Ð¼Ñ Ð½Ð° базовом ÑÑовне ÑазбеÑÑмÑÑ Ð² иÑ
ÑÑÑÑойÑÑве.
| ÐÑимеÑаниÑ: | ЧÑÐ¾Ð±Ñ Ð»ÑÑÑе понÑÑÑ Ð¼Ð°ÑеÑиал, желаÑелÑно пеÑед ÑÑением ознакомиÑÑÑÑ Ñ Ð¾Ñновами JavaScript, аÑÐ¸Ð½Ñ ÑоннÑми опеÑаÑиÑми вообÑе и обÑекÑами Promises. |
|---|---|
| Ð¦ÐµÐ»Ñ Ð¼Ð°ÑеÑиала: | ÐаÑÑиÑÑ Ð¿Ð¸ÑаÑÑ ÑовÑеменнÑй аÑÐ¸Ð½Ñ ÑоннÑй код Ñ Ð¸ÑполÑзованием Promises и async functions. |
ÐÑÐ½Ð¾Ð²Ñ async/await
>ÐлÑÑевое Ñлово async
ÐлÑÑевое Ñлово async позволÑÐµÑ ÑделаÑÑ Ð¸Ð· обÑÑной ÑÑнкÑии (function declaration или function expression) аÑинÑ
ÑоннÑÑ ÑÑнкÑÐ¸Ñ (async function). Ð¢Ð°ÐºÐ°Ñ ÑÑнкÑÐ¸Ñ Ð´ÐµÐ»Ð°ÐµÑ Ð´Ð²Ðµ веÑи:
- ÐбоÑаÑÐ¸Ð²Ð°ÐµÑ Ð²Ð¾Ð·Ð²ÑаÑаемое знаÑение в Promise
- ÐозволÑÐµÑ Ð¸ÑполÑзоваÑÑ ÐºÐ»ÑÑевое Ñлово await (Ñм. далÑÑе)
ÐопÑобÑйÑе вÑполниÑÑ Ð² конÑоли бÑаÑзеÑа ÑледÑÑÑий код:
function hello() {
return "Hello";
}
hello();
ФÑнкÑÐ¸Ñ Ð²Ð¾Ð·Ð²ÑаÑÐ°ÐµÑ "Hello" â ниÑего необÑÑного, веÑно?
Ðо ÑÑо еÑли Ð¼Ñ Ñделаем ÐµÑ Ð°ÑÐ¸Ð½Ñ Ñонной? ÐÑовеÑим:
async function hello() {
return "Hello";
}
hello();
Ðак бÑло Ñказано Ñанее, вÑзов аÑÐ¸Ð½Ñ Ñонной ÑÑнкÑии возвÑаÑÐ°ÐµÑ Ð¾Ð±ÑÐµÐºÑ Promise.
ÐÐ¾Ñ Ð¿ÑÐ¸Ð¼ÐµÑ Ñ async function expression:
const hello = async function () {
return "Hello";
};
hello();
Также можно иÑполÑзоваÑÑ ÑÑÑелоÑнÑе ÑÑнкÑии:
const hello = async () => {
return "Hello";
};
ÐÑе они в обÑем ÑлÑÑае делаÑÑ Ð¾Ð´Ð½Ð¾ и Ñо же.
ЧÑÐ¾Ð±Ñ Ð¿Ð¾Ð»ÑÑиÑÑ Ð·Ð½Ð°Ñение, коÑоÑое возвÑаÑÐ°ÐµÑ Promise, Ð¼Ñ ÐºÐ°Ðº обÑÑно можем иÑполÑзоваÑÑ Ð¼ÐµÑод .then():
hello().then((value) => console.log(value));
или еÑÑ ÐºÐ¾ÑоÑе
hello().then(console.log);
ÐÑак, клÑÑевое Ñлово async, пÑевÑаÑÐ°ÐµÑ Ð¾Ð±ÑÑнÑÑ ÑÑнкÑÐ¸Ñ Ð² аÑинÑ
ÑоннÑÑ Ð¸ ÑезÑлÑÑÐ°Ñ Ð²Ñзова ÑÑнкÑии обоÑаÑÐ¸Ð²Ð°ÐµÑ Ð² Promise. Также аÑинÑ
ÑÐ¾Ð½Ð½Ð°Ñ ÑÑнкÑÐ¸Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»ÑÐµÑ Ð¸ÑполÑзоваÑÑ Ð² ÑвоÑм Ñеле клÑÑевое Ñлово await, о коÑоÑом далее.
ÐлÑÑевое Ñлово await
ÐÑинÑ
ÑоннÑе ÑÑнкÑии ÑÑановÑÑÑÑ Ð¿Ð¾ наÑÑоÑÑÐµÐ¼Ñ Ð¼Ð¾ÑнÑми, когда Ð²Ñ Ð¸ÑполÑзÑеÑе клÑÑевое Ñлово await â по ÑакÑÑ, await ÑабоÑÐ°ÐµÑ ÑолÑко в аÑинÑ
ÑоннÑÑ
ÑÑнкÑиÑÑ
. ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ иÑполÑзоваÑÑ await пеÑед promise-based ÑÑнкÑией, ÑÑÐ¾Ð±Ñ Ð¾ÑÑановиÑÑ Ð¿Ð¾Ñок вÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¸ дождаÑÑÑÑ ÑезÑлÑÑаÑа ÐµÑ Ð²ÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ (ÑезÑлÑÑÐ°Ñ Promise). Ð Ñо же вÑемÑ, оÑÑалÑной код наÑего пÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð½Ðµ блокиÑÑеÑÑÑ Ð¸ пÑÐ¾Ð´Ð¾Ð»Ð¶Ð°ÐµÑ ÑабоÑаÑÑ.
ÐÑ Ð¼Ð¾Ð¶ÐµÑе иÑполÑзоваÑÑ await пеÑед лÑбой ÑÑнкÑией, коÑоÑÐ°Ñ Ð²Ð¾Ð·Ð²ÑаÑÐ°ÐµÑ Promise, вклÑÑÐ°Ñ Browser API ÑÑнкÑии.
ÐеболÑÑой пÑимеÑ:
async function hello() {
return (greeting = await Promise.resolve("Hello"));
}
hello().then(alert);
ÐонеÑно, на пÑакÑике код вÑÑе беÑполезен, но в ÑÑебнÑÑ ÑелÑÑ Ð¾Ð½ иллÑÑÑÑиÑÑÐµÑ ÑинÑакÑÐ¸Ñ Ð°ÑÐ¸Ð½Ñ ÑоннÑÑ ÑÑнкÑий. ТепеÑÑ Ð´Ð°Ð²Ð°Ð¹Ñе пеÑейдÑм к ÑеалÑнÑм пÑимеÑам.
ÐеÑепиÑÑваем Promises Ñ Ð¸ÑполÑзованием async/await
ÐавайÑе поÑмоÑÑим на пÑÐ¸Ð¼ÐµÑ Ð¸Ð· пÑедÑдÑÑей ÑÑаÑÑи:
fetch("coffee.jpg")
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
} else {
return response.blob();
}
})
.then((myBlob) => {
const objectURL = URL.createObjectURL(myBlob);
const image = document.createElement("img");
image.src = objectURL;
document.body.appendChild(image);
})
.catch((e) => {
console.log(
"There has been a problem with your fetch operation: " + e.message,
);
});
Ð ÑÑÐ¾Ð¼Ñ Ð¼Ð¾Ð¼ÐµÐ½ÑÑ Ð²Ñ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¿Ð¾Ð½Ð¸Ð¼Ð°ÑÑ ÐºÐ°Ðº ÑабоÑаÑÑ Promises, ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð½ÑÑÑ Ð²Ñе оÑÑалÑное. ÐавайÑе пеÑепиÑем код иÑполÑзÑÑ async/await и оÑеним ÑазниÑÑ.
async function myFetch() {
const response = await fetch("coffee.jpg");
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
} else {
const myBlob = await response.blob();
const objectURL = URL.createObjectURL(myBlob);
const image = document.createElement("img");
image.src = objectURL;
document.body.appendChild(image);
}
}
myFetch().catch((e) => {
console.log(
"There has been a problem with your fetch operation: " + e.message,
);
});
СоглаÑиÑеÑÑ, ÑÑо код ÑÑал коÑоÑе и понÑÑнее â болÑÑе никакиÑ
блоков .then() по вÑÐµÐ¼Ñ ÑкÑипÑÑ!
Так как клÑÑевое Ñлово async заÑÑавлÑÐµÑ ÑÑнкÑÐ¸Ñ Ð²ÐµÑнÑÑÑ Promise, Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ иÑполÑзоваÑÑ Ð³Ð¸Ð±ÑиднÑй подÑ
од:
async function myFetch() {
const response = await fetch("coffee.jpg");
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
} else {
return await response.blob();
}
}
myFetch()
.then((blob) => {
const objectURL = URL.createObjectURL(blob);
const image = document.createElement("img");
image.src = objectURL;
document.body.appendChild(image);
})
.catch((e) => console.log(e));
ÐожеÑе попÑакÑиковаÑÑÑÑ ÑамоÑÑоÑÑелÑно, или запÑÑÑиÑÑ Ð½Ð°Ñ live example (а Ñакже source code).
ÐинÑÑоÑкÑ, а как ÑÑо вÑе ÑабоÑаеÑ?
ÐÑ Ð¼Ð¾Ð³Ð»Ð¸ замеÑиÑÑ, ÑÑо Ð¼Ñ Ð¾Ð±ÐµÑнÑли Ð½Ð°Ñ ÐºÐ¾Ð´ в ÑÑнкÑÐ¸Ñ Ð¸ Ñделали ÐµÑ Ð°ÑинÑ
Ñонной Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ async. ÐÑо бÑло обÑзаÑелÑно â нам надо ÑоздаÑÑ ÐºÐ¾Ð½ÑейнеÑ, внÑÑÑи коÑоÑого бÑÐ´ÐµÑ Ð·Ð°Ð¿ÑÑкаÑÑÑÑ Ð°ÑинÑ
ÑоннÑй код, и бÑÐ´ÐµÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑÑ Ð´Ð¾Ð¶Ð´Ð°ÑÑÑÑ ÐµÐ³Ð¾ ÑезÑлÑÑаÑа Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ await, не блокиÑÑÑ Ð¾ÑÑалÑной код наÑего ÑкÑипÑа.
ÐнÑÑÑи myFetch() наÑ
одиÑÑÑ ÐºÐ¾Ð´, коÑоÑÑй Ñлегка Ð½Ð°Ð¿Ð¾Ð¼Ð¸Ð½Ð°ÐµÑ Ð²ÐµÑÑÐ¸Ñ Ð½Ð° Promise, но еÑÑÑ Ð²Ð°Ð¶Ð½Ñе оÑлиÑиÑ. ÐмеÑÑо Ñого, ÑÑÐ¾Ð±Ñ Ð¿Ð¸ÑаÑÑ ÑепоÑÐºÑ Ð±Ð»Ð¾ÐºÐ¾Ð² .then() Ð¼Ñ Ð¿ÑоÑÑо иÑполÑзÑÐµÑ ÐºÐ»ÑÑевое Ñлово await пеÑед вÑзовом promise-based ÑÑнкÑии и пÑиÑваиваем ÑезÑлÑÑÐ°Ñ Ð² пеÑеменнÑÑ. ÐлÑÑевое Ñлово await говоÑÐ¸Ñ JavaScript runtime пÑиоÑÑановиÑÑ ÐºÐ¾Ð´ в ÑÑой ÑÑÑоке, не блокиÑÑÑ Ð¾ÑÑалÑной код ÑкÑипÑа за пÑеделами аÑинÑ
Ñонной ÑÑнкÑии. Ðогда вÑзов promise-based ÑÑнкÑии бÑÐ´ÐµÑ Ð³Ð¾Ñов веÑнÑÑÑ ÑезÑлÑÑаÑ, вÑполнение пÑодолжиÑÑÑ Ñ ÑÑой ÑÑÑоки далÑÑе.
ÐÑимеÑ:
const response = await fetch("coffee.jpg");
ÐнаÑение Promise, коÑоÑое веÑнÑÑ fetch() бÑÐ´ÐµÑ Ð¿ÑиÑвоено пеÑеменной response ÑолÑко Ñогда, когда оно бÑÐ´ÐµÑ Ð´Ð¾ÑÑÑпно â паÑÑÐµÑ Ð´ÐµÐ»Ð°ÐµÑ Ð¿Ð°ÑÐ·Ñ Ð½Ð° данной ÑÑÑоке дожидаÑÑÑ ÑÑого моменÑа. Ðак ÑолÑко знаÑение доÑÑÑпно, паÑÑÐµÑ Ð¿ÐµÑеÑ
Ð¾Ð´Ð¸Ñ Ðº ÑледÑÑÑей ÑÑÑоке, в коÑоÑой ÑоздаÑÑÑÑ Ð¾Ð±ÑÐµÐºÑ Blob из ÑезÑлÑÑаÑа Promise. Ð ÑÑой ÑÑÑоке, кÑÑаÑи, Ñакже иÑполÑзÑеÑÑÑ await, поÑÐ¾Ð¼Ñ ÑÑо меÑод .blob() Ñакже возвÑаÑÐ°ÐµÑ Promise. Ðогда ÑезÑлÑÑÐ°Ñ Ð³Ð¾Ñов, Ð¼Ñ Ð²Ð¾Ð·Ð²ÑаÑаем его наÑÑÐ¶Ñ Ð¸Ð· myFetch().
ÐбÑаÑиÑе внимание, когда Ð¼Ñ Ð²ÑзÑваем myFetch(), она возвÑаÑÐ°ÐµÑ Promise, поÑÑÐ¾Ð¼Ñ Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ вÑзваÑÑ .then() на ÑезÑлÑÑаÑе, ÑÑÐ¾Ð±Ñ Ð¾ÑобÑазиÑÑ ÐµÐ³Ð¾ на ÑкÑане.
Ð ÑÑÐ¾Ð¼Ñ Ð¼Ð¾Ð¼ÐµÐ½ÑÑ Ð²Ñ Ð½Ð°Ð²ÐµÑное дÑмаеÑе "ÐÑо ÑеалÑно кÑÑÑо!", и Ð²Ñ Ð¿ÑÐ°Ð²Ñ â Ñем менÑÑе блоков .then(), Ñем легÑе ÑиÑаÑÑ ÐºÐ¾Ð´.
ÐобавлÑем обÑабоÑÐºÑ Ð¾Ñибок
ЧÑÐ¾Ð±Ñ Ð¾Ð±ÑабоÑаÑÑ Ð¾Ñибки Ñ Ð½Ð°Ñ ÐµÑÑÑ Ð½ÐµÑколÑко ваÑианÑов.
ÐÑ Ð¼Ð¾Ð¶ÐµÐ¼ иÑполÑзоваÑÑ ÑинÑ
ÑоннÑÑ try...catch ÑÑÑÑкÑÑÑÑ Ñ async/await. ÐÐ¾Ñ Ð¸Ð·Ð¼ÐµÐ½ÑÐ½Ð½Ð°Ñ Ð²ÐµÑÑÐ¸Ñ Ð¿ÐµÑвого пÑимеÑа вÑÑе:
async function myFetch() {
try {
const response = await fetch("coffee.jpg");
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
} else {
const myBlob = await response.blob();
const objectURL = URL.createObjectURL(myBlob);
const image = document.createElement("img");
image.src = objectURL;
document.body.appendChild(image);
}
} catch (e) {
console.log(e);
}
}
myFetch();
Рблок catch() {} пеÑедаÑÑÑÑ Ð¾Ð±ÑÐµÐºÑ Ð¾Ñибки, коÑоÑÑй Ð¼Ñ Ð½Ð°Ð·Ð²Ð°Ð»Ð¸ e; Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ вÑвеÑÑи его в конÑолÑ, ÑÑÐ¾Ð±Ñ Ð¿Ð¾ÑмоÑÑеÑÑ Ð´ÐµÑали: где и поÑÐµÐ¼Ñ Ð²Ð¾Ð·Ð½Ð¸ÐºÐ»Ð° оÑибка.
ÐÑли Ð²Ñ Ñ
оÑиÑе иÑполÑзоваÑÑ Ð³Ð¸Ð±ÑиднÑй подÑ
од (пÑÐ¸Ð¼ÐµÑ Ð²ÑÑе), лÑÑÑе иÑполÑзоваÑÑ Ð±Ð»Ð¾Ðº .catch() поÑле блока .then() Ð²Ð¾Ñ Ñак:
async function myFetch() {
const response = await fetch("coffee.jpg");
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
} else {
return await response.blob();
}
}
myFetch()
.then((blob) => {
const objectURL = URL.createObjectURL(blob);
const image = document.createElement("img");
image.src = objectURL;
document.body.appendChild(image);
})
.catch((e) => console.log(e));
Так лÑÑÑе, поÑÐ¾Ð¼Ñ ÑÑо блок .catch() ÑÐ»Ð¾Ð²Ð¸Ñ Ð¾Ñибки как из аÑинÑ
Ñонной ÑÑнкÑии, Ñак и из Promise. ÐÑли Ð±Ñ Ð¼Ñ Ð¸ÑполÑзовали блок try/catch, Ð¼Ñ Ð±Ñ Ð½Ðµ Ñловили оÑибкÑ, коÑоÑÐ°Ñ Ð¿ÑоизоÑла в Ñамой myFetch() ÑÑнкÑии.
ÐÑ Ð¼Ð¾Ð¶ÐµÑе поÑмоÑÑеÑÑ Ð¾Ð±Ð° пÑимеÑа на GitHub:
- simple-fetch-async-await-try-catch.html (ÑмоÑÑеÑÑ source code)
- simple-fetch-async-await-promise-catch.html (ÑмоÑÑеÑÑ source code)
Await и Promise.all()
Ðак Ð²Ñ Ð¿Ð¾Ð¼Ð½Ð¸Ñе, аÑинÑ
ÑоннÑе ÑÑнкÑии поÑÑÑÐ¾ÐµÐ½Ñ Ð¿Ð¾Ð²ÐµÑÑ
promises, поÑÑÐ¾Ð¼Ñ Ð¾Ð½Ð¸ ÑовмеÑÑÐ¸Ð¼Ñ Ñо вÑеми возможноÑÑÑми поÑледниÑ
. ÐÑ Ð»ÐµÐ³ÐºÐ¾ можем подождаÑÑ Ð²Ñполнение Promise.all(), пÑиÑвоиÑÑ ÑезÑлÑÑÐ°Ñ Ð² пеÑеменнÑÑ Ð¸ вÑе ÑÑо ÑделаÑÑ Ð¸ÑполÑзÑÑ ÑинÑ
ÑоннÑй ÑÑилÑ.
ÐеÑÑÐ¸Ñ Ñ async/await (ÑмоÑÑиÑе live demo и source code) вÑглÑÐ´Ð¸Ñ Ñак:
async function fetchAndDecode(url, type) {
const response = await fetch(url);
let content;
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
} else {
if (type === "blob") {
content = await response.blob();
} else if (type === "text") {
content = await response.text();
}
return content;
}
}
async function displayContent() {
const coffee = fetchAndDecode("coffee.jpg", "blob");
const tea = fetchAndDecode("tea.jpg", "blob");
const description = fetchAndDecode("description.txt", "text");
const values = await Promise.all([coffee, tea, description]);
const objectURL1 = URL.createObjectURL(values[0]);
const objectURL2 = URL.createObjectURL(values[1]);
const descText = values[2];
const image1 = document.createElement("img");
const image2 = document.createElement("img");
image1.src = objectURL1;
image2.src = objectURL2;
document.body.appendChild(image1);
document.body.appendChild(image2);
const para = document.createElement("p");
para.textContent = descText;
document.body.appendChild(para);
}
displayContent().catch((e) => console.log(e));
ÐзглÑниÑе на ÑÑÑÐ¾ÐºÑ Ñ Promise.all():
const values = await Promise.all([coffee, tea, description]);
С помоÑÑÑ await Ð¼Ñ Ð¶Ð´Ñм маÑÑив ÑезÑлÑÑаÑов вÑеÑ
ÑÑÑÑ
Promises и пÑиÑваиваем его в пеÑеменнÑÑ values. ÐÑо аÑинÑ
ÑоннÑй код, но он напиÑан в ÑинÑ
Ñонном ÑÑиле, за ÑÑÑÑ Ñего он гоÑаздо ÑиÑабелÑнее.
ÐÑ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¾Ð±ÐµÑнÑÑÑ Ð²ÐµÑÑ ÐºÐ¾Ð´ в аÑинÑ
ÑоннÑÑ ÑÑнкÑиÑ, displayContent(), и Ð¼Ñ Ð½Ðµ ÑилÑно ÑÑкономили на колиÑеÑÑве кода, но Ð¼Ñ Ð¸Ð·Ð²Ð»ÐµÐºÐ»Ð¸ код блока .then(), за ÑÑÑÑ Ñего Ð½Ð°Ñ ÐºÐ¾Ð´ ÑÑал гоÑаздо ÑиÑе.
ÐÐ»Ñ Ð¾Ð±ÑабоÑки оÑибок Ð¼Ñ Ð´Ð¾Ð±Ð°Ð²Ð¸Ð»Ð¸ блок .catch() Ð´Ð»Ñ ÑÑнкÑии displayContent(); ÐÑо позволило нам оÑловиÑÑ Ð¾Ñибки в обоиÑ
ÑÑнкÑиÑÑ
.
ÐÑимеÑание:
ÐÑ Ñакже можем иÑполÑзоваÑÑ ÑинÑ
ÑоннÑй блок finally внÑÑÑи аÑинÑ
Ñонной ÑÑнкÑии, вмеÑÑо аÑинÑ
Ñонного .finally(), ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð»ÑÑиÑÑ Ð¸Ð½ÑоÑмаÑÐ¸Ñ Ð¾ ÑезÑлÑÑаÑе наÑей опеÑаÑии â ÑмоÑÑиÑе в дейÑÑвии в наÑем live example (ÑмоÑÑиÑе source code).
ÐедоÑÑаÑки async/await
ÐÑинÑ
ÑоннÑе ÑÑнкÑии Ñ async/await бÑваÑÑ Ð¾ÑÐµÐ½Ñ ÑдобнÑми, но еÑÑÑ Ð½ÐµÑколÑко замеÑаний, о коÑоÑÑÑ
полезно знаÑÑ.
async/await позволÑÐµÑ Ð²Ð°Ð¼ пиÑаÑÑ ÐºÐ¾Ð´ в ÑинÑ
Ñонном ÑÑиле. ÐлÑÑевое Ñлово await блокиÑÑÐµÑ Ð¿ÑиоÑÑÐ°Ð½Ð°Ð²Ð»Ð¸Ð²Ð°ÐµÑ Ð²Ñполнение promise-based ÑÑнкÑии до Ñого моменÑа, пока promise пÑÐ¸Ð¼ÐµÑ ÑÑаÑÑÑ fulfilled. ÐÑо не блокиÑÑÐµÑ ÐºÐ¾Ð´ за пÑеделами ваÑей аÑинÑ
Ñонной ÑÑнкÑии, Ñем не менее важно помниÑÑ, ÑÑо внÑÑÑи аÑинÑ
Ñонной ÑÑнкÑии поÑок вÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð±Ð»Ð¾ÐºÐ¸ÑÑеÑÑÑ.
ÐÐ°Ñ ÐºÐ¾Ð´ Ð¼Ð¾Ð¶ÐµÑ ÑÑаÑÑ Ð¼ÐµÐ´Ð»ÐµÐ½Ð½ÐµÐµ за ÑÑÑÑ Ð±Ð¾Ð»ÑÑого колиÑеÑÑва awaited promises, коÑоÑÑе идÑÑ Ð¾Ð´Ð¸Ð½ за дÑÑгим. ÐаждÑй await должен дождаÑÑÑÑ Ð²ÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¿ÑедÑдÑÑего, Ñогда как на Ñамом деле Ð¼Ñ Ñ
оÑим, ÑÑÐ¾Ð±Ñ Ð½Ð°Ñи Promises вÑполнÑлиÑÑ Ð¾Ð´Ð½Ð¾Ð²Ñеменно, как еÑли Ð±Ñ Ð¼Ñ Ð½Ðµ иÑполÑзовали async/await.
ÐÑÑÑ Ð¿Ð¾Ð´Ñ Ð¾Ð´, коÑоÑÑй позволÑÐµÑ Ð¾Ð±Ð¾Ð¹Ñи ÑÑÑ Ð¿ÑÐ¾Ð±Ð»ÐµÐ¼Ñ â ÑÐ¾Ñ ÑаниÑÑ Ð²Ñе вÑполнÑÑÑиеÑÑ Promises в пеÑеменнÑе, а Ñже поÑле ÑÑого дожидаÑÑÑÑ (awaiting) Ð¸Ñ ÑезÑлÑÑаÑа. ÐавайÑе поÑмоÑÑим на неÑколÑко пÑимеÑов.
ÐÑ Ð¿Ð¾Ð´Ð³Ð¾Ñовили два пÑимеÑа â slow-async-await.html (Ñм. source code) и fast-async-await.html (Ñм. source code). Ðни оба наÑинаÑÑÑÑ Ñ ÑÑнкÑии возвÑаÑаÑÑей promise, имиÑиÑÑÑÑей аÑинÑ
ÑонноÑÑÑ Ð¿ÑоÑеÑÑов пÑи помоÑи вÑзова setTimeout():
function timeoutPromise(interval) {
return new Promise((resolve, reject) => {
setTimeout(function () {
resolve("done");
}, interval);
});
}
Ðалее в каждом пÑимеÑе еÑÑÑ Ð°ÑинÑ
ÑÐ¾Ð½Ð½Ð°Ñ ÑÑнкÑÐ¸Ñ timeTest() ожидаÑÑÐ°Ñ ÑÑи вÑзова timeoutPromise():
async function timeTest() {
await timeoutPromise(3000);
await timeoutPromise(3000);
await timeoutPromise(3000);
}
Ркаждом пÑимеÑе ÑÑнкÑÐ¸Ñ Ð·Ð°Ð¿Ð¸ÑÑÐ²Ð°ÐµÑ Ð²ÑÐµÐ¼Ñ Ð½Ð°Ñала иÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¸ ÑколÑко вÑемени понадобилоÑÑ Ð½Ð° иÑполнение timeTest() пÑомиÑов, вÑÑиÑÐ°Ñ Ð²ÑÐµÐ¼Ñ Ð² Ð¼Ð¾Ð¼ÐµÐ½Ñ Ð·Ð°Ð¿ÑÑка ÑÑнкÑии из вÑемени в Ð¼Ð¾Ð¼ÐµÐ½Ñ ÑазÑеÑÐµÐ½Ð¸Ñ Ð¿ÑомиÑов:
const startTime = Date.now();
timeTest().then(() => {
const finishTime = Date.now();
const timeTaken = finishTime - startTime;
alert("Time taken in milliseconds: " + timeTaken);
});
Ðалее пÑедÑÑавлена аÑинÑ
ÑÐ¾Ð½Ð½Ð°Ñ ÑÑнкÑÐ¸Ñ timeTest() ÑазлиÑÐ½Ð°Ñ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ из пÑимеÑов.
Ð ÑлÑÑае Ñ Ð¼ÐµÐ´Ð»ÐµÐ½Ð½Ñм пÑимеÑом slow-async-await.html, timeTest() вÑглÑдиÑ:
async function timeTest() {
await timeoutPromise(3000);
await timeoutPromise(3000);
await timeoutPromise(3000);
}
ÐдеÑÑ Ð¼Ñ Ð¿ÑоÑÑо ждÑм вÑе ÑÑи timeoutPromise() напÑÑмÑÑ, блокиÑÑÑ Ð²Ñполнение на данного блока на 3 ÑекÑÐ½Ð´Ñ Ð¿Ñи каждом вÑзове. ÐÑе поÑледÑÑÑие вÑÐ·Ð¾Ð²Ñ Ð²ÑнÑÐ¶Ð´ÐµÐ½Ñ Ð¶Ð´Ð°ÑÑ Ð¿Ð¾ÐºÐ° ÑазÑеÑиÑÑÑ Ð¿ÑедÑдÑÑий. ÐÑли Ð²Ñ Ð·Ð°Ð¿ÑÑÑиÑе пеÑвÑй пÑÐ¸Ð¼ÐµÑ (slow-async-await.html), Ñо ÑвидиÑе alert ÑообÑаÑÑий вÑÐµÐ¼Ñ Ð²ÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¾ÐºÐ¾Ð»Ð¾ 9 ÑекÑнд.
Ðо вÑоÑом fast-async-await.html пÑимеÑе, ÑÑнкÑÐ¸Ñ timeTest() вÑглÑÐ´Ð¸Ñ Ñак:
async function timeTest() {
const timeoutPromise1 = timeoutPromise(3000);
const timeoutPromise2 = timeoutPromise(3000);
const timeoutPromise3 = timeoutPromise(3000);
await timeoutPromise1;
await timeoutPromise2;
await timeoutPromise3;
}
Рданном ÑлÑÑае Ð¼Ñ Ñ
Ñаним ÑÑи обÑекÑа Promise в пеÑеменнÑÑ
, каждÑй из коÑоÑÑÑ
Ð¼Ð¾Ð¶ÐµÑ ÑазÑеÑиÑÑÑÑ Ð½ÐµÐ·Ð°Ð²Ð¸Ñимо Ð¾Ñ Ð´ÑÑгиÑ
.
Ðиже Ð¼Ñ Ð¾Ð¶Ð¸Ð´Ð°ÐµÐ¼ ÑазÑеÑÐµÐ½Ð¸Ñ Ð¿ÑомиÑов из обÑекÑа в ÑезÑлÑÑаÑ. Так как они бÑли запÑÑÐµÐ½Ð½Ñ Ð¾Ð´Ð½Ð¾Ð²Ñеменно, блокиÑÑÑ Ð¿Ð¾Ñок, Ñо и ÑазÑеÑаÑÑÑ Ð¾Ð´Ð½Ð¾Ð²Ñеменно. ÐÑли Ð²Ñ Ð·Ð°Ð¿ÑÑÑиÑе вÑоÑой пÑÐ¸Ð¼ÐµÑ Ð²Ñ ÑвидиÑе alert, ÑообÑаÑÑий вÑÐµÐ¼Ñ Ð²ÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð¾ÐºÐ¾Ð»Ð¾ 3 ÑекÑнд.
Ðажно не забÑваÑÑ Ð¾ бÑÑÑÑодейÑÑвии пÑименÑÑ await, пÑовеÑÑйÑе колиÑеÑÑво блокиÑовок.
Async/await class methods
РкаÑеÑÑве поÑледнего замеÑаниÑ, Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе иÑполÑзоваÑÑ async пеÑед меÑодами клаÑÑов или обÑекÑов, вÑнÑÐ¶Ð´Ð°Ñ Ð¸Ñ
возвÑаÑаÑÑ promises. Ð Ñакже await внÑÑÑи меÑодов обÑÑвленнÑÑ
Ñаким обÑазом. ÐоÑмоÑÑиÑе на пÑÐ¸Ð¼ÐµÑ ES class code, коÑоÑÑй Ð¼Ñ Ð²Ð¸Ð´ÐµÐ»Ð¸ в ÑÑаÑÑе object-oriented JavaScript и ÑÑавниÑе его Ñ Ð¼Ð¾Ð´Ð¸ÑиÑиÑованной (аÑинÑ
Ñонной) async веÑÑией ниже:
class Person {
constructor(first, last, age, gender, interests) {
this.name = {
first,
last,
};
this.age = age;
this.gender = gender;
this.interests = interests;
}
async greeting() {
return await Promise.resolve(`Hi! I'm ${this.name.first}`);
}
farewell() {
console.log(`${this.name.first} has left the building. Bye for now!`);
}
}
const han = new Person("Han", "Solo", 25, "male", ["Smuggling"]);
ÐеÑвÑй меÑод клаÑÑа ÑепеÑÑ Ð¼Ð¾Ð¶Ð½Ð¾ иÑполÑзоваÑÑ Ñаким обÑазом:
han.greeting().then(console.log);
Browser support (ÐоддеÑжка бÑаÑзеÑами)
Ðдним из кÑиÑеÑиев пÑи пÑинÑÑии ÑеÑÐµÐ½Ð¸Ñ Ð¾Ð± иÑполÑзовании async/await ÑвлÑеÑÑÑ Ð¿Ð¾Ð´Ð´ÐµÑжка ÑÑаÑÑÑ
бÑаÑзеÑов. async/await, как и Promises, доÑÑÑÐ¿Ð½Ñ Ð² болÑÑинÑÑве ÑовÑеменнÑÑ
бÑаÑзеÑов. РоÑновном, пÑÐ¾Ð±Ð»ÐµÐ¼Ñ Ñ Ð¿Ð¾Ð´Ð´ÐµÑжкой могÑÑ Ð²Ð¾Ð·Ð½Ð¸ÐºÐ½ÑÑÑ Ð² Internet Explorer и Opera Mini.
ÐÑли Ð²Ñ Ñ
оÑиÑе иÑполÑзоваÑÑ async/await, но пÑи ÑÑом беÑпокоиÑеÑÑ Ð¾ поддеÑжке ÑÑаÑÑÑ
бÑаÑзеÑов, можно ÑаÑÑмоÑÑеÑÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑÑ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð±Ð¸Ð±Ð»Ð¸Ð¾Ñеки BabelJS â она позволÑÐµÑ Ð¿Ð¸ÑаÑÑ Ð¿ÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñ Ð¸ÑполÑзованием новейÑего JavaScript и Ð¼Ð¾Ð¶ÐµÑ Ð°Ð²ÑомаÑиÑеÑки пÑедоÑÑавлÑÑÑ Ð¿Ð¾Ð»Ð¸ÑиллÑ, коÑоÑÑе ÑабоÑаÑÑ Ð² ÑÑаÑÑÑ
бÑаÑзеÑаÑ
, в каÑеÑÑве запаÑнÑÑ
ваÑианÑов.
ÐаклÑÑение
ÐÐ¾Ñ Ð¿Ð¾Ð¶Ð°Ð»Ñй и вÑе â async/await позволÑÑÑ Ð¿Ð¸ÑаÑÑ Ð°ÑинÑ
ÑоннÑй код, коÑоÑÑй легÑе ÑиÑаÑÑ Ð¸ поддеÑживаÑÑ. Ðаже ÑÑиÑÑваÑ, ÑÑо поддеÑжка Ñо ÑÑоÑÐ¾Ð½Ñ Ð±ÑаÑзеÑов неÑколÑко Ñ
Ñже, Ñем Ñ promise.then, вÑÑ Ð¶Ðµ ÑÑÐ¾Ð¸Ñ Ð¾Ð±ÑаÑиÑÑ Ð½Ð° него внимание.