ãã®èšäºã®èè
ã¯ãJavaScript ã«ããã Async/Await ã®äŸã調ã¹ãŠããŸãã å
šäœãšããŠãAsync/Await ã¯éåæã³ãŒããäœæãã䟿å©ãªæ¹æ³ã§ãã ãã®æ©èœãç»å Žããåã¯ããã®ãããªã³ãŒãã¯ã³ãŒã«ããã¯ãšãããã¹ã䜿çšããŠèšè¿°ãããŠããŸããã å
ã®èšäºã®èè
ã¯ãããŸããŸãªäŸãåæããããšã§ Async/Await ã®å©ç¹ãæããã«ããŠããŸãã
ãªãã€ã³ããŒïŒ ãHabrãã®ãã¹ãŠã®èªè ã察象 - ãHabrãããã¢ãŒã·ã§ã³ ã³ãŒãã䜿çšããŠã¹ãã«ããã¯ã¹ ã³ãŒã¹ã«ç»é²ãããš 10 ã«ãŒãã«ã®å²åŒã
ã¹ãã«ããã¯ã¹ã¯æ¬¡ã®ããšãæšå¥šããŸãã æè²ãªã³ã©ã€ã³ã³ãŒã¹
ãJavaéçºè ã .
ã³ãŒââã«ããã¯
ã³ãŒã«ããã¯ã¯ãåŒã³åºããç¡æéã«é 延ãããé¢æ°ã§ãã 以åã¯ãçµæãããã«ååŸã§ããªãã³ãŒãé åã§ã³ãŒã«ããã¯ã䜿çšãããŠããŸããã
以äžã¯ãNode.js ã§ãã¡ã€ã«ãéåæçã«èªã¿åãäŸã§ãã
fs.readFile(__filename, 'utf-8', (err, data) => {
if (err) {
throw err;
}
console.log(data);
});
è€æ°ã®éåææäœãäžåºŠã«å®è¡ããå¿
èŠãããå Žåãåé¡ãçºçããŸãã 次ã®ã·ããªãªãæ³åããŠã¿ãŸããããArfat ãŠãŒã¶ãŒ ããŒã¿ããŒã¹ã«å¯ŸããŠãªã¯ãšã¹ããè¡ããããã® profile_img_url ãã£ãŒã«ããèªã¿åããsomeserver.com ãµãŒããŒããç»åãããŠã³ããŒãããå¿
èŠããããŸãã
ããŠã³ããŒãåŸãç»åãå¥ã®åœ¢åŒãããšãã° PNG ãã JPEG ã«å€æããŸãã å€æãæåãããšããŠãŒã¶ãŒã®é»åã¡ãŒã«ã«ã¬ã¿ãŒãéä¿¡ãããŸãã 次ã«ãã€ãã³ãã«é¢ããæ
å ±ããæ¥ä»ã瀺ãtransformations.log ãã¡ã€ã«ã«å
¥åãããŸãã
ã³ãŒãã®æåŸã®éšåã«ããã³ãŒã«ããã¯ã®éè€ãšå€æ°ã® }) ã«æ³šæããå¿ èŠããããŸãã ããã¯ã³ãŒã«ããã¯å°çãŸãã¯ç Žæ» ã®ãã©ããããšåŒã°ããŸãã
ãã®æ¹æ³ã®æ¬ ç¹ã¯æããã§ãã
- ãã®ã³ãŒãã¯èªã¿ã«ããã§ãã
- ãšã©ãŒã®åŠçãé£ãããã³ãŒãã®å質ãäœäžããããšããããããŸãã
ãã®åé¡ã解決ããããã«ãPromise ã JavaScript ã«è¿œå ãããŸããã ããã«ãããã³ãŒã«ããã¯ã®æ·±ããã¹ãã .then ãšããåèªã«çœ®ãæããããšãã§ããŸãã
Promise ã®è¯ãé¢ã¯ãã³ãŒããå·Šããå³ã§ã¯ãªãäžããäžã«èªã¿ãããããããšã§ãã ãã ããPromise ã«ã¯åé¡ããããŸãã
- .then ã倧éã«è¿œå ããå¿ èŠããããŸãã
- try/catch ã®ä»£ããã«ã.catch ã䜿çšããŠãã¹ãŠã®ãšã©ãŒãåŠçãããŸãã
- XNUMX ã€ã®ã«ãŒãå ã§è€æ°ã® Promise ãæ±ãããšã¯å¿ ããã䟿å©ã§ãããšã¯éããŸãããå Žåã«ãã£ãŠã¯ãã³ãŒããè€éã«ãªããŸãã
ããã§ã¯ãæåŸã®ç¹ã®æå³ã瀺ãåé¡ã瀺ããŸãã
0 ãã 10 ãŸã§ã®äžé£ã®æ°å€ãã©ã³ãã ãªéé (0 ïœ n ç§) ã§åºåãã for ã«ãŒãããããšããŸãã Promise ã䜿çšããŠãæ°å€ã 0 ãã 10 ãŸã§é çªã«åºåãããããã«ãã®ã«ãŒããå€æŽããå¿ èŠããããŸããã€ãŸãã6 ãåºåããã®ã« 2 ç§ããããXNUMX ãåºåããã®ã« XNUMX ç§ãããå Žåã¯ãæåã« XNUMX ãåºåãããã®åŸã«åºåããå¿ èŠããããŸããå°å·ã®ã«ãŠã³ãããŠã³ãå§ãŸããŸãã
ãããŠãã¡ããããã®åé¡ã解決ããããã« Async/Await ã .sort ã¯äœ¿çšããŸããã 解決çã®äŸã¯æåŸã«ãããŸãã
éåæé¢æ°
ES2017 (ES8) ã«éåæé¢æ°ãè¿œå ãããããšã§ãPromise ãæ±ãã¿ã¹ã¯ãç°¡çŽ åãããŸããã async é¢æ°ã¯ Promise ã®ãäžã§ãåäœããããšã«æ³šæããŠãã ããã ãããã®é¢æ°ã¯ã質çã«ç°ãªãæŠå¿µãè¡šããã®ã§ã¯ãããŸããã éåæé¢æ°ã¯ãPromise ã䜿çšããã³ãŒãã®ä»£æ¿ãšããŠæå³ãããŠããŸãã
Async/Await ã䜿çšãããšãéåæã³ãŒãã䜿çšããäœæ¥ãåæã¹ã¿ã€ã«ã§æŽçã§ããŸãã
ãããã£ãŠãPromise ãç解ãããšãAsync/Await ã®ååãç解ãããããªããŸãã
æ§æ
éåžžããã㯠async ãš await ã® XNUMX ã€ã®ããŒã¯ãŒãã§æ§æãããŸãã æåã®åèªã¯é¢æ°ãéåæã«å€æããŸãã ãã®ãããªé¢æ°ã§ã¯ await ã䜿çšã§ããŸãã ãã以å€ã®å Žåããã®é¢æ°ã䜿çšãããšãšã©ãŒãçºçããŸãã
// With function declaration
async function myFn() {
// await ...
}
// With arrow function
const myFn = async () => {
// await ...
}
function myFn() {
// await fn(); (Syntax Error since no async)
}
Async ã¯é¢æ°å®£èšã®å é ãã¢ããŒé¢æ°ã®å Žåã¯ã=ãèšå·ãšæ¬åŒ§ã®éã«æ¿å ¥ãããŸãã
ãããã®é¢æ°ã¯ãã¡ãœãããšããŠãªããžã§ã¯ãã«é 眮ããããšããã¯ã©ã¹å®£èšã§äœ¿çšããããšãã§ããŸãã
// As an object's method
const obj = {
async getName() {
return fetch('https://www.example.com');
}
}
// In a class
class Obj {
async getResource() {
return fetch('https://www.example.com');
}
}
泚æïŒ ã¯ã©ã¹ ã³ã³ã¹ãã©ã¯ã¿ãŒãšã²ãã¿ãŒ/ã»ãã¿ãŒã¯éåæã«ã§ããªãããšãèŠããŠãã䟡å€ããããŸãã
ã»ãã³ãã£ã¯ã¹ãšå®è¡ã«ãŒã«
éåæé¢æ°ã¯åºæ¬çã«æšæºã® JS é¢æ°ãšäŒŒãŠããŸãããäŸå€ããããŸãã
ãããã£ãŠãéåæé¢æ°ã¯åžžã« Promise ãè¿ããŸãã
async function fn() {
return 'hello';
}
fn().then(console.log)
// hello
å ·äœçã«ã¯ãfn ã¯æåå hello ãè¿ããŸãã ããã¯éåæé¢æ°ã§ãããããæååå€ã¯ã³ã³ã¹ãã©ã¯ã¿ãŒã䜿çšã㊠Promise ã«ã©ãããããŸãã
éåæã䜿çšããªã代æ¿èšèšã¯æ¬¡ã®ãšããã§ãã
function fn() {
return Promise.resolve('hello');
}
fn().then(console.log);
// hello
ãã®å ŽåãPromise ã¯ãæåãã§è¿ãããŸãã éåæé¢æ°ã¯åžžã«æ°ãã Promise ã§ã©ãããããŸãã
æ»ãå€ãããªããã£ãã®å Žåãasync é¢æ°ã¯å€ã Promise ã§ã©ããããŠè¿ããŸãã æ»ãå€ã Promise ãªããžã§ã¯ãã®å Žåããã®è§£æ±ºã¯æ°ãã Promise ã§è¿ãããŸãã
const p = Promise.resolve('hello')
p instanceof Promise;
// true
Promise.resolve(p) === p;
// true
ããããéåæé¢æ°å ã§ãšã©ãŒãçºçããå Žåã¯ã©ããªãã§ãããã?
async function foo() {
throw Error('bar');
}
foo().catch(console.log);
åŠçãããªãå Žåãfoo() ã¯æåŠä»ãã® Promise ãè¿ããŸãã ãã®ç¶æ³ã§ã¯ãPromise.resolve ã®ä»£ããã«ããšã©ãŒãå«ã Promise.reject ãè¿ãããŸãã
éåæé¢æ°ã¯ãäœãè¿ããããã«é¢ä¿ãªããåžžã« Promise ãåºåããŸãã
éåæé¢æ°ã¯ await ããšã«äžæåæ¢ããŸãã
Await ã¯åŒã«åœ±é¿ããŸãã ãããã£ãŠãåŒã Promise ã§ããå Žåãasync é¢æ°ã¯ Promise ãæºãããããŸã§äžæåæ¢ãããŸãã åŒã Promise ã§ã¯ãªãå ŽåãPromise.resolve ã«ãã£ãŠ Promise ã«å€æãããŠå®äºããŸãã
// utility function to cause delay
// and get random value
const delayAndGetRandom = (ms) => {
return new Promise(resolve => setTimeout(
() => {
const val = Math.trunc(Math.random() * 100);
resolve(val);
}, ms
));
};
async function fn() {
const a = await 9;
const b = await delayAndGetRandom(1000);
const c = await 5;
await delayAndGetRandom(1000);
return a + b * c;
}
// Execute fn
fn().then(console.log);
ããã§ã¯ãfn é¢æ°ãã©ã®ããã«æ©èœãããã説æããŸãã
- åŒã³åºãåŸã®æåã®è¡ã¯ const a = await 9; ããå€æãããŸãã const a = await Promise.resolve(9);ã
- Await ã䜿çšããåŸãé¢æ°ã®å®è¡ã¯ã a ããã®å€ (çŸåšã®ç¶æ³ã§ã¯ 9) ãååŸãããŸã§äžæåæ¢ãããŸãã
- lateAndGetRandom(1000) ã¯ãé¢æ°èªäœãå®äºãããŸã§ (1 ç§åŸ) fn é¢æ°ã®å®è¡ãäžæåæ¢ããŸãã ããã«ãããfn æ©èœã 1 ç§éå®è³ªçã«åæ¢ãããŸãã
- replaceAndGetRandom(1000) ã¯ãresolve ãä»ããŠã©ã³ãã ãªå€ãè¿ãããããå€æ° b ã«å²ãåœãŠãããŸãã
- ããŠãå€æ° c ã®å Žåã¯å€æ° a ã®å ŽåãšäŒŒãŠããŸãã ãã®åŸããã¹ãŠãäžç¬åæ¢ããŸãããdelayAndGetRandom(1000) ã¯å¿ èŠãªããããäœãè¿ããŸããã
- ãã®çµæãå€ã¯åŒ a + b * c ã䜿çšããŠèšç®ãããŸãã çµæ㯠Promise.resolve ã䜿çšã㊠Promise ã«ã©ãããããé¢æ°ã«ãã£ãŠè¿ãããŸãã
ãããã®äžæåæ¢ã¯ ES6 ã®ãžã§ãã¬ãŒã¿ãŒãæãåºããããããããŸããããããã«ã¯äœãããããŸã
åé¡ã®è§£æ±º
ããŠãäžã§è¿°ã¹ãåé¡ã®è§£æ±ºçãèŠãŠã¿ãŸãããã
finishMyTask é¢æ°ã¯ãAwait ã䜿çšããŠãqueryDatabaseãsendEmailãlogTaskInFile ãªã©ã®æäœã®çµæãåŸ ã¡ãŸãã ãã®ãœãªã¥ãŒã·ã§ã³ã Promise ã䜿çšãããœãªã¥ãŒã·ã§ã³ãšæ¯èŒãããšãé¡äŒŒç¹ãæããã«ãªããŸãã ãã ããAsync/Await ããŒãžã§ã³ã§ã¯ããã¹ãŠã®è€éãªæ§æãå€§å¹ ã«ç°¡çŽ åãããŠããŸãã ãã®å Žåã.then/.catch ã®ãããªå€æ°ã®ã³ãŒã«ããã¯ããã§ãŒã³ã¯ãããŸããã
ããã§ã¯æ°å€ãåºåãããœãªã¥ãŒã·ã§ã³ã瀺ããŸãããªãã·ã§ã³ã¯ XNUMX ã€ãããŸãã
const wait = (i, ms) => new Promise(resolve => setTimeout(() => resolve(i), ms));
// Implementation One (Using for-loop)
const printNumbers = () => new Promise((resolve) => {
let pr = Promise.resolve(0);
for (let i = 1; i <= 10; i += 1) {
pr = pr.then((val) => {
console.log(val);
return wait(i, Math.random() * 1000);
});
}
resolve(pr);
});
// Implementation Two (Using Recursion)
const printNumbersRecursive = () => {
return Promise.resolve(0).then(function processNextPromise(i) {
if (i === 10) {
return undefined;
}
return wait(i, Math.random() * 1000).then((val) => {
console.log(val);
return processNextPromise(i + 1);
});
});
};
ãããŠãããã¯éåæé¢æ°ã䜿çšãã解決çã§ãã
async function printNumbersUsingAsync() {
for (let i = 0; i < 10; i++) {
await wait(i, Math.random() * 1000);
console.log(i);
}
}
ÐбÑабПÑка ПÑОбПк
æªåŠçã®ãšã©ãŒã¯ãæåŠããã Promise ã«ã©ãããããŸãã ãã ããéåæé¢æ°ã¯ try/catch ã䜿çšããŠãšã©ãŒãåæçã«åŠçã§ããŸãã
async function canRejectOrReturn() {
// wait one second
await new Promise(res => setTimeout(res, 1000));
// Reject with ~50% probability
if (Math.random() > 0.5) {
throw new Error('Sorry, number too big.')
}
return 'perfect number';
}
canRejectOrReturn() ã¯ãæåããã (ãå®å šãªæ°å€ã)ããšã©ãŒã§å€±æãã (ãç³ãèš³ãããŸãããæ°å€ã倧ããããŸãã) éåæé¢æ°ã§ãã
async function foo() {
try {
await canRejectOrReturn();
} catch (e) {
return 'error caught';
}
}
äžèšã®äŸã§ã¯ canRejectOrReturn ã®å®è¡ãæ³å®ãããŠãããããããèªäœã倱æãããš catch ãããã¯ãå®è¡ãããŸãã ãã®çµæãé¢æ° foo ã¯æªå®çŸ© (try ãããã¯ã§äœãè¿ãããªãå Žå) ãŸãã¯ãšã©ãŒããã£ãããããŠçµäºããŸãã ãã®çµæãtry/catch ãé¢æ° foo èªäœãåŠçããããããã®é¢æ°ã¯å€±æããŸããã
å¥ã®äŸã次ã«ç€ºããŸãã
async function foo() {
try {
return canRejectOrReturn();
} catch (e) {
return 'error caught';
}
}
ãã®äŸã§ã¯ãfoo ãã canRejectOrReturn ãè¿ãããããšã«æ³šæããŠãã ããã ãã®å ŽåãFoo ã¯å®å šãªæ°å€ã§çµäºãããããšã©ãŒ (ãç³ãèš³ãããŸãããæ°å€ã倧ããããŸãã) ãè¿ããŸãã catch ãããã¯ã¯æ±ºããŠå®è¡ãããŸããã
åé¡ã¯ãfoo ã canRejectOrReturn ããæž¡ããã Promise ãè¿ãããšã§ãã ãããã£ãŠãfoo ã«å¯Ÿãã解決ç㯠canRejectOrReturn ã«å¯Ÿãã解決çã«ãªããŸãã ãã®å Žåãã³ãŒã㯠XNUMX è¡ã®ã¿ã§æ§æãããŸãã
try {
const promise = canRejectOrReturn();
return promise;
}
await ãš return ãäžç·ã«äœ¿çšãããšã©ããªããã¯æ¬¡ã®ãšããã§ãã
async function foo() {
try {
return await canRejectOrReturn();
} catch (e) {
return 'error caught';
}
}
äžèšã®ã³ãŒãã§ã¯ãfoo ã¯å®å šæ°ãšãšã©ãŒã®äž¡æ¹ããã£ããããŠæ£åžžã«çµäºããŸãã ããã§æåŠã¯ãããŸããã ãã ããfoo 㯠unknown ã§ã¯ãªããcanRejectOrReturn ã§æ»ããŸãã return await canRejectOrReturn() è¡ãåé€ããŠãããã確èªããŸãããã
try {
const value = await canRejectOrReturn();
return value;
}
// âŠ
ããããééããšèœãšãç©Ž
å Žåã«ãã£ãŠã¯ãAsync/Await ã䜿çšãããšãšã©ãŒãçºçããå¯èœæ§ããããŸãã
å¿ãããããŸãŸåŸ ã£ãŠããŸã
ããã¯éåžžã«é »ç¹ã«çºçããŸããPromise ã®åã« await ããŒã¯ãŒããå¿ããããŠããŸãã
async function foo() {
try {
canRejectOrReturn();
} catch (e) {
return 'caught';
}
}
ã芧ã®ãšãããã³ãŒãã«ã¯ await ã return ããããŸããã ãããã£ãŠãfoo ã¯åžžã« 1 ç§ã®é 延ãªã undefine ã§çµäºããŸãã ããããçŽæã¯å¿ ãæããããŸãã ãšã©ãŒãŸãã¯æåŠãã¹ããŒãããå Žåã¯ãUnhandledPromiseRejectionWarning ãåŒã³åºãããŸãã
ã³ãŒã«ããã¯ã®éåæé¢æ°
éåæé¢æ°ã¯ã.map ãŸã㯠.filter ã§ã³ãŒã«ããã¯ãšããŠãã䜿çšãããŸãã äŸãšããŠã¯ãGitHub äžã§éããŠãããªããžããªã®æ°ãè¿ã fetchPublicReposCount(username) é¢æ°ããããŸãã ã¡ããªã¯ã¹ãå¿ èŠãªãŠãŒã¶ãŒã XNUMX 人ãããšããŸãã ãã®ã¿ã¹ã¯ã®ã³ãŒãã¯æ¬¡ã®ãšããã§ãã
const url = 'https://api.github.com/users';
// Utility fn to fetch repo counts
const fetchPublicReposCount = async (username) => {
const response = await fetch(`${url}/${username}`);
const json = await response.json();
return json['public_repos'];
}
ArfatSalmanãoctocatãnorvig ã®ã¢ã«ãŠã³ããå¿ èŠã§ãã ãã®å Žåã次ã®ããã«ããŸãã
const users = [
'ArfatSalman',
'octocat',
'norvig'
];
const counts = users.map(async username => {
const count = await fetchPublicReposCount(username);
return count;
});
.map ã³ãŒã«ããã¯ã® Await ã«æ³šæãã䟡å€ããããŸãã ããã§ãcounts 㯠Promise ã®é åã§ããã.map ã¯æå®ãããåãŠãŒã¶ãŒã®å¿åã³ãŒã«ããã¯ã§ãã
await ã®é床ã«äžè²«ãã䜿çš
ãã®ã³ãŒããäŸãšããŠèŠãŠã¿ãŸãããã
async function fetchAllCounts(users) {
const counts = [];
for (let i = 0; i < users.length; i++) {
const username = users[i];
const count = await fetchPublicReposCount(username);
counts.push(count);
}
return counts;
}
ããã§ã¯ããªããžããªçªå·ã count å€æ°ã«é 眮ããããã®çªå·ã counts é åã«è¿œå ãããŸãã ãã®ã³ãŒãã®åé¡ã¯ãæåã®ãŠãŒã¶ãŒã®ããŒã¿ããµãŒããŒããå°çãããŸã§ãåŸç¶ã®ãŠãŒã¶ãŒã¯ãã¹ãŠã¹ã¿ã³ã〠ã¢ãŒãã«ãªãããšã§ãã ãããã£ãŠãäžåºŠã«åŠçããããŠãŒã¶ãŒã¯ XNUMX 人ã ãã§ãã
ããšãã°ã300 人ã®ãŠãŒã¶ãŒã®åŠçã«çŽ XNUMX ããªç§ãããå Žåããã¹ãŠã®ãŠãŒã¶ãŒã§ã¯ãã§ã« XNUMX ç§ã«ãªã£ãŠãããè²»ããããæéã¯ãŠãŒã¶ãŒã®æ°ã«çŽç·çã«äŸåããŸãã ãã ãããªããžããªæ°ã®ååŸã¯çžäºã«äŸåããªããããåŠçã䞊ååããããšãã§ããŸãã ããã«ã¯ã.map ãš Promise.all ãæäœããå¿ èŠããããŸãã
async function fetchAllCounts(users) {
const promises = users.map(async username => {
const count = await fetchPublicReposCount(username);
return count;
});
return Promise.all(promises);
}
Promise.all ã¯ãPromise ã®é åãå ¥åãšããŠåãåããPromise ãè¿ããŸãã åŸè ã¯ãé åå ã®ãã¹ãŠã® Promise ãå®äºããåŸããŸãã¯æåã®æåŠæã«å®äºããŸãã ãã¹ãŠãåæã«éå§ããªãå ŽåããããŸãã確å®ã«åæéå§ããã«ã¯ãp-map ã䜿çšããŸãã
ãŸãšã
éçºã«ãšã£ãŠéåæé¢æ°ã¯ãŸããŸãéèŠã«ãªã£ãŠããŸãã ããã§ãããéåæé¢æ°ãé©å¿çã«äœ¿çšããã«ã¯ã䜿çšãã䟡å€ããããŸã
ã¹ãã«ããã¯ã¹ã¯æ¬¡ã®ããšãæšå¥šããŸãã
- å®è·µã³ãŒã¹
ãã¢ãã€ã«ããããããŒPROã .- ãªã³ã©ã€ã³ã³ãŒã¹ã®ç³ã蟌ã¿
ãPythonã§åŠã¶ããŒã¿ã¢ããªã¹ãã .- XNUMX幎éã®å®è·µã³ãŒã¹
ãç§ã¯ããã®ãŠã§ãéçºè ã§ãã .
åºæïŒ habr.com