ื‘ื•ืื• ื ืกืชื›ืœ ืขืœ Async/Await ื‘-JavaScript ื‘ืืžืฆืขื•ืช ื“ื•ื’ืžืื•ืช

ื›ื•ืชื‘ ื”ืžืืžืจ ื‘ื•ื—ืŸ ื“ื•ื’ืžืื•ืช ืฉืœ Async/Await ื‘-JavaScript. ื‘ืกืš ื”ื›ืœ, Async/Await ื”ื™ื ื“ืจืš ื ื•ื—ื” ืœื›ืชื•ื‘ ืงื•ื“ ืืกื™ื ื›ืจื•ื ื™. ืœืคื ื™ ืฉื”ืคื™ืฆ'ืจ ื”ื–ื” ื”ื•ืคื™ืข, ืงื•ื“ ื›ื–ื” ื ื›ืชื‘ ื‘ืืžืฆืขื•ืช ื”ืชืงืฉืจื•ื™ื•ืช ื•ื”ื‘ื˜ื—ื•ืช. ืžื—ื‘ืจ ื”ืžืืžืจ ื”ืžืงื•ืจื™ ื—ื•ืฉืฃ ืืช ื”ื™ืชืจื•ื ื•ืช ืฉืœ Async/Await ืขืœ ื™ื“ื™ ื ื™ืชื•ื— ื“ื•ื’ืžืื•ืช ืฉื•ื ื•ืช.

ืื ื• ืžื–ื›ื™ืจื™ื: ืœื›ืœ ืงื•ืจืื™ Habr - ื”ื ื—ื” ืฉืœ 10 ืจื•ื‘ืœ ื‘ืขืช ื”ืจืฉืžื” ืœื›ืœ ืงื•ืจืก Skillbox ื‘ืืžืฆืขื•ืช ืงื•ื“ ื”ื”ื˜ื‘ื” ืฉืœ Habr.

Skillbox ืžืžืœื™ืฆื”: ืงื•ืจืก ื—ื™ื ื•ื›ื™ ืžืงื•ื•ืŸ "ืžืคืชื— ื’'ืื•ื•ื”".

Callback

ื”ืชืงืฉืจื•ืช ื—ื•ื–ืจืช ื”ื™ื ืคื•ื ืงืฆื™ื” ืฉื”ืฉื™ื—ื” ืฉืœื” ืžืชืขื›ื‘ืช ืœืœื ื”ื’ื‘ืœืช ื–ืžืŸ. ื‘ืขื‘ืจ ื ืขืฉื” ืฉื™ืžื•ืฉ ื‘ื”ืชืงืฉืจื•ืช ื—ื•ื–ืจืช ื‘ืื•ืชื ืื–ื•ืจื™ ืงื•ื“ ืฉื‘ื”ื ืœื ื ื™ืชืŸ ื”ื™ื” ืœื”ืฉื™ื’ ืืช ื”ืชื•ืฆืื” ื‘ืื•ืคืŸ ืžื™ื™ื“ื™.

ื”ื ื” ื“ื•ื’ืžื” ืœืงืจื™ืื” ืืกื™ื ื›ืจื•ื ื™ืช ืฉืœ ืงื•ื‘ืฅ ื‘-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, ื”ืžืฆื™ื™ืŸ ืืช ื”ืชืืจื™ืš.

ื›ื“ืื™ ืœืฉื™ื ืœื‘ ืœื—ืคื™ืคื” ืฉืœ ืฉื™ื—ื•ืช ื—ื•ื–ืจื•ืช ื•ืœืžืกืคืจ ื”ืจื‘ ืฉืœ }) ื‘ื—ืœืง ื”ืื—ืจื•ืŸ ืฉืœ ื”ืงื•ื“. ื–ื” ื ืงืจื Callback Hell ืื• Pyramid of Doom.

ื”ื—ืกืจื•ื ื•ืช ืฉืœ ืฉื™ื˜ื” ื–ื• ื‘ืจื•ืจื™ื:

  • ืงืฉื” ืœืงืจื•ื ืืช ื”ืงื•ื“ ื”ื–ื”.
  • ืงืฉื” ื’ื ืœื˜ืคืœ ื‘ืฉื’ื™ืื•ืช, ืžื” ืฉืžื•ื‘ื™ืœ ืœืจื•ื‘ ืœืื™ื›ื•ืช ืงื•ื“ ื™ืจื•ื“ื”.

ื›ื“ื™ ืœืคืชื•ืจ ื‘ืขื™ื” ื–ื•, ื ื•ืกืคื• ื”ื‘ื˜ื—ื•ืช ืœ-JavaScript. ื”ื ืžืืคืฉืจื™ื ืœืš ืœื”ื—ืœื™ืฃ ืงื™ื ื•ืŸ ืขืžื•ืง ืฉืœ ื”ืชืงืฉืจื•ื™ื•ืช ื—ื•ื–ืจื•ืช ื‘ืžื™ืœื” .then.

ื”ื”ื™ื‘ื˜ ื”ื—ื™ื•ื‘ื™ ืฉืœ ื”ื‘ื˜ื—ื•ืช ื”ื•ื ืฉื”ืŸ ื”ื•ืคื›ื•ืช ืืช ื”ืงื•ื“ ืœืงืจื™ืื” ื”ืจื‘ื” ื™ื•ืชืจ ื˜ื•ื‘, ืžืœืžืขืœื” ืœืžื˜ื” ื•ืœื ืžืฉืžืืœ ืœื™ืžื™ืŸ. ืขื ื–ืืช, ืœื”ื‘ื˜ื—ื•ืช ื™ืฉ ื’ื ื‘ืขื™ื•ืช:

  • ืืชื” ืฆืจื™ืš ืœื”ื•ืกื™ืฃ ื”ืจื‘ื” .ืื–.
  • ื‘ืžืงื•ื try/catch, ื ืขืฉื” ืฉื™ืžื•ืฉ ื‘-.catch ืœื˜ื™ืคื•ืœ ื‘ื›ืœ ื”ืฉื’ื™ืื•ืช.
  • ืขื‘ื•ื“ื” ืขื ื”ื‘ื˜ื—ื•ืช ืžืจื•ื‘ื•ืช ื‘ืชื•ืš ืœื•ืœืื” ืื—ืช ื”ื™ื ืœื ืชืžื™ื“ ื ื•ื—ื”; ื‘ืžืงืจื™ื ืžืกื•ื™ืžื™ื, ื”ืŸ ืžืกื‘ื›ื•ืช ืืช ื”ืงื•ื“.

ื”ื ื” ื‘ืขื™ื” ืฉืชืจืื” ืืช ื”ืžืฉืžืขื•ืช ืฉืœ ื”ื ืงื•ื“ื” ื”ืื—ืจื•ื ื”.

ื ื ื™ื— ืฉื™ืฉ ืœื ื• ืœื•ืœืืช for ืฉืžื“ืคื™ืกื” ืจืฆืฃ ืฉืœ ืžืกืคืจื™ื ืž-0 ืขื“ 10 ื‘ืžืจื•ื•ื—ื™ื ืืงืจืื™ื™ื (0-n ืฉื ื™ื•ืช). ื‘ืืžืฆืขื•ืช ื”ื‘ื˜ื—ื•ืช, ืขืœื™ืš ืœืฉื ื•ืช ืœื•ืœืื” ื–ื• ื›ืš ืฉื”ืžืกืคืจื™ื ื™ื•ื“ืคืกื• ื‘ืจืฆืฃ ืž-0 ืขื“ 10. ืœื›ืŸ, ืื ืœื•ืงื— 6 ืฉื ื™ื•ืช ืœื”ื“ืคื™ืก ืืคืก ื•-2 ืฉื ื™ื•ืช ืœื”ื“ืคื™ืก XNUMX, ื™ืฉ ืœื”ื“ืคื™ืก ืชื—ื™ืœื” ืืช ื”ืืคืก, ื•ืœืื—ืจ ืžื›ืŸ. ื”ืกืคื™ืจื” ืœืื—ื•ืจ ืœื”ื“ืคืกืช ื–ื” ืชืชื—ื™ืœ.

ื•ื›ืžื•ื‘ืŸ, ืื ื—ื ื• ืœื ืžืฉืชืžืฉื™ื ื‘-Async/Await ืื• ื‘-.sort ื›ื“ื™ ืœืคืชื•ืจ ื‘ืขื™ื” ื–ื•. ืคืชืจื•ืŸ ืœื“ื•ื’ืžื” ื ืžืฆื ื‘ืกื•ืฃ.

ืคื•ื ืงืฆื™ื•ืช ืืกื™ื ื›ืจื•ืŸ

ื”ื•ืกืคืช ืคื•ื ืงืฆื™ื•ืช ืืกื™ื ื›ืจื•ืŸ ื‘-ES2017 (ES8) ืคืฉื˜ื” ืืช ืžืฉื™ืžืช ื”ืขื‘ื•ื“ื” ืขื ื”ื‘ื˜ื—ื•ืช. ืื ื™ ืžืฆื™ื™ืŸ ืฉืคื•ื ืงืฆื™ื•ืช ืืกื™ื ื›ืจื•ืŸ ืขื•ื‘ื“ื•ืช "ืขืœ ื”ื‘ื˜ื—ื•ืช". ืคื•ื ืงืฆื™ื•ืช ืืœื• ืื™ื ืŸ ืžื™ื™ืฆื’ื•ืช ืžื•ืฉื’ื™ื ืฉื•ื ื™ื ืžื‘ื—ื™ื ื” ืื™ื›ื•ืชื™ืช. ืคื•ื ืงืฆื™ื•ืช ืืกื™ื ื›ืจื•ืŸ ื ื•ืขื“ื• ื›ื—ืœื•ืคื” ืœืงื•ื“ ื”ืžืฉืชืžืฉ ื‘ื”ื‘ื˜ื—ื•ืช.

Async/Await ืžืืคืฉืจ ืœืืจื’ืŸ ืขื‘ื•ื“ื” ืขื ืงื•ื“ ืืกื™ื ื›ืจื•ื ื™ ื‘ืกื’ื ื•ืŸ ืกื™ื ื›ืจื•ื ื™.

ืœืคื™ื›ืš, ื™ื“ื™ืขืช ื”ื‘ื˜ื—ื•ืช ืžืงืœื” ืขืœ ื”ื‘ื ืช ื”ืขืงืจื•ื ื•ืช ืฉืœ Async/Await.

ืชื—ื‘ื™ืจ

ื‘ื“ืจืš ื›ืœืœ ื”ื•ื ืžื•ืจื›ื‘ ืžืฉืชื™ ืžื™ืœื•ืช ืžืคืชื—: ืืกื™ื ื›ืจื•ืŸ ื•ื”ืžืชื ื”. ื”ืžื™ืœื” ื”ืจืืฉื•ื ื” ื”ื•ืคื›ืช ืืช ื”ืคื•ื ืงืฆื™ื” ืœื-ืกื™ื ื›ืจื•ื ื™ืช. ืคื•ื ืงืฆื™ื•ืช ื›ืืœื” ืžืืคืฉืจื•ืช ืืช ื”ืฉื™ืžื•ืฉ ื‘- wait. ื‘ื›ืœ ืžืงืจื” ืื—ืจ, ืฉื™ืžื•ืฉ ื‘ืคื•ื ืงืฆื™ื” ื–ื• ื™ื™ืฆื•ืจ ืฉื’ื™ืื”.

// 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');
  }
}

NB! ื›ื“ืื™ ืœื–ื›ื•ืจ ืฉื‘ื ืื™ ืžื—ืœืงื•ืช ื•ื’ื˜ืจื™ื/ืžื’ื“ื™ืจื™ื ืื™ื ื ื™ื›ื•ืœื™ื ืœื”ื™ื•ืช ืืกื™ื ื›ืจื•ื ื™ื™ื.

ืกืžื ื˜ื™ืงื” ื•ื›ืœืœื™ ื‘ื™ืฆื•ืข

ืคื•ื ืงืฆื™ื•ืช ืืกื™ื ื›ืจื•ืŸ ื“ื•ืžื•ืช ื‘ืขืฆื ืœืคื•ื ืงืฆื™ื•ืช JS ืกื˜ื ื“ืจื˜ื™ื•ืช, ืื‘ืœ ื™ืฉ ื™ื•ืฆืื™ื ืžืŸ ื”ื›ืœืœ.

ืœืคื™ื›ืš, ืคื•ื ืงืฆื™ื•ืช ืืกื™ื ื›ืจื•ืŸ ืชืžื™ื“ ืžื—ื–ื™ืจื•ืช ื”ื‘ื˜ื—ื•ืช:

async function fn() {
  return 'hello';
}
fn().then(console.log)
// hello

ื‘ืื•ืคืŸ ืกืคืฆื™ืคื™, fn ืžื—ื–ื™ืจื” ืืช ื”ืžื—ืจื•ื–ืช hello. ื•ื‘ื›ืŸ, ืžื›ื™ื•ื•ืŸ ืฉื–ื• ืคื•ื ืงืฆื™ื” ืืกื™ื ื›ืจื•ื ื™ืช, ืขืจืš ื”ืžื—ืจื•ื–ืช ืขื˜ื•ืฃ ื‘ื”ื‘ื˜ื—ื” ื‘ืืžืฆืขื•ืช ื‘ื ืื™.

ืœื”ืœืŸ ืขื™ืฆื•ื‘ ื—ืœื•ืคื™ ืœืœื ืืกื™ื ื›ืจื•ืŸ:

function fn() {
  return Promise.resolve('hello');
}
 
fn().then(console.log);
// hello

ื‘ืžืงืจื” ื–ื”, ื”ื”ื‘ื˜ื—ื” ืžื•ื—ื–ืจืช "ื™ื“ื ื™ืช". ืคื•ื ืงืฆื™ื” ืืกื™ื ื›ืจื•ื ื™ืช ืขื˜ื•ืคื” ืชืžื™ื“ ื‘ื”ื‘ื˜ื—ื” ื—ื“ืฉื”.

ืื ืขืจืš ื”ื”ื—ื–ืจื” ื”ื•ื ืคืจื™ืžื™ื˜ื™ื‘ื™, ื”ืคื•ื ืงืฆื™ื” ืืกื™ื ื›ืจื•ืŸ ืžื—ื–ื™ืจื” ืืช ื”ืขืจืš ืขืœ ื™ื“ื™ ื’ืœื™ืฉืชื• ื‘ื”ื‘ื˜ื—ื”. ืื ืขืจืš ื”ื”ื—ื–ืจื” ื”ื•ื ืื•ื‘ื™ื™ืงื˜ ื”ื‘ื˜ื—ื”, ื”ืจื–ื•ืœื•ืฆื™ื” ืฉืœื• ืžื•ื—ื–ืจืช ื‘ื”ื‘ื˜ื—ื” ื—ื“ืฉื”.

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.reject ื”ืžื›ื™ืœ ืฉื’ื™ืื” ื™ื•ื—ื–ืจ ื‘ืžืงื•ื Promise.resolve.

ืคื•ื ืงืฆื™ื•ืช ืืกื™ื ื›ืจื•ืŸ ืชืžื™ื“ ืžื•ืฆื™ืื•ืช ื”ื‘ื˜ื—ื”, ืœืœื ืงืฉืจ ืœืžื” ืฉืžื•ื—ื–ืจ.

ืคื•ื ืงืฆื™ื•ืช ืืกื™ื ื›ืจื•ื ื™ื•ืช ืขื•ืฆืจื•ืช ื‘ื›ืœ ื”ืžืชื ื”.

ืœื”ืžืชื™ืŸ ืžืฉืคื™ืข ืขืœ ื‘ื™ื˜ื•ื™ื™ื. ืœื›ืŸ, ืื ื”ื‘ื™ื˜ื•ื™ ื”ื•ื ื”ื‘ื˜ื—ื”, ืคื•ื ืงืฆื™ื™ืช ื”ืืกื™ื ื›ืจื•ืŸ ืžื•ืฉืขื” ืขื“ ืœืžื™ืžื•ืฉ ื”ื”ื‘ื˜ื—ื”. ืื ื”ื‘ื™ื˜ื•ื™ ืื™ื ื• ื”ื‘ื˜ื—ื”, ื”ื•ื ืžื•ืžืจ ืœื”ื‘ื˜ื—ื” ื‘ืืžืฆืขื•ืช Promise.resolve ื•ืœืื—ืจ ืžื›ืŸ ื”ื•ืฉืœื.

// 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; in const a = await Promise.resolve(9);.
  • ืœืื—ืจ ื”ืฉื™ืžื•ืฉ ื‘-Await, ื‘ื™ืฆื•ืข ื”ืคื•ื ืงืฆื™ื” ืžื•ืฉืขื” ืขื“ ืฉ-a ืžืงื‘ืœ ืืช ื”ืขืจืš ืฉืœื” (ื‘ืžืฆื‘ ื”ื ื•ื›ื—ื™ ื”ื•ื 9).
  • delayAndGetRandom(1000) ืžืฉื”ื” ืืช ื‘ื™ืฆื•ืข ื”ืคื•ื ืงืฆื™ื” fn ืขื“ ืฉื”ื™ื ืžืฉืœื™ืžื” ืืช ืขืฆืžื” (ืœืื—ืจ ืฉื ื™ื™ื” ืื—ืช). ื–ื” ืœืžืขืฉื” ืžืคืกื™ืง ืืช ืคื•ื ืงืฆื™ื™ืช fn ืœืžืฉืš ืฉื ื™ื™ื” ืื—ืช.
  • delayAndGetRandom(1000) via resolve ืžื—ื–ื™ืจ ืขืจืš ืืงืจืื™, ืืฉืจ ืžื•ืงืฆื” ืœืื—ืจ ืžื›ืŸ ืœืžืฉืชื ื” b.
  • ื•ื‘ื›ืŸ, ื”ืžืงืจื” ืขื ืžืฉืชื ื” c ื“ื•ืžื” ืœืžืงืจื” ืขื ืžืฉืชื ื” a. ืœืื—ืจ ืžื›ืŸ, ื”ื›ืœ ื ืขืฆืจ ืœืฉื ื™ื™ื”, ืืš ื›ืขืช delayAndGetRandom(1000) ืœื ืžื—ื–ื™ืจ ื“ื‘ืจ ื›ื™ ื–ื” ืœื ื ื“ืจืฉ.
  • ื›ืชื•ืฆืื” ืžื›ืš, ื”ืขืจื›ื™ื ืžื—ื•ืฉื‘ื™ื ื‘ืืžืฆืขื•ืช ื”ื ื•ืกื—ื” a + b * c. ื”ืชื•ืฆืื” ืขื˜ื•ืคื” ื‘ื”ื‘ื˜ื—ื” ื‘ืืžืฆืขื•ืช Promise.resolve ื•ืžื•ื—ื–ืจืช ืขืœ ื™ื“ื™ ื”ืคื•ื ืงืฆื™ื”.

ื”ื”ืคืกืงื•ืช ื”ืืœื” ืื•ืœื™ ืžื–ื›ื™ืจื•ืช ื’ื ืจื˜ื•ืจื™ื ื‘-ES6, ืื‘ืœ ื™ืฉ ื‘ื–ื” ืžืฉื”ื• ื”ืกื™ื‘ื•ืช ืฉืœืš.

ืคืชืจื•ืŸ ื”ื‘ืขื™ื”

ื•ื‘ื›ืŸ, ืขื›ืฉื™ื• ื‘ื•ืื• ื ืกืชื›ืœ ืขืœ ื”ืคืชืจื•ืŸ ืœื‘ืขื™ื” ืฉื”ื•ื–ื›ืจื” ืœืขื™ืœ.

ื”ืคื•ื ืงืฆื™ื” finishMyTask ืžืฉืชืžืฉืช ื‘-Await ื›ื“ื™ ืœื”ืžืชื™ืŸ ืœืชื•ืฆืื•ืช ืฉืœ ืคืขื•ืœื•ืช ื›ื’ื•ืŸ queryDatabase, sendEmail, logTaskInFile ื•ืื—ืจื•ืช. ืื ืชืฉื•ื•ื” ืืช ื”ืคืชืจื•ืŸ ื”ื–ื” ืœื–ื” ืฉื‘ื• ื ืขืฉื” ืฉื™ืžื•ืฉ ื‘ื”ื‘ื˜ื—ื•ืช, ืงื•ื•ื™ ื”ื“ืžื™ื•ืŸ ื™ืชื‘ืจืจื•. ืขื ื–ืืช, ื’ืจืกืช Async/Await ืžืคืฉื˜ืช ืžืื•ื“ ืืช ื›ืœ ื”ืžื•ืจื›ื‘ื•ื™ื•ืช ื”ืชื—ื‘ื™ืจื™ื•ืช. ื‘ืžืงืจื” ื–ื”, ืื™ืŸ ืžืกืคืจ ื’ื“ื•ืœ ืฉืœ ื”ืชืงืฉืจื•ื™ื•ืช ื•ืจืฉืชื•ืช ื›ืžื• .then/.catch.

ืœื”ืœืŸ ืคืชืจื•ืŸ ืขื ืคืœื˜ ืฉืœ ืžืกืคืจื™ื, ื™ืฉ ืฉืชื™ ืืคืฉืจื•ื™ื•ืช.

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);
  }
}

ืฉื’ื™ืื” ื‘ืขื™ื‘ื•ื“

ืฉื’ื™ืื•ืช ืœื ืžื˜ื•ืคืœื•ืช ืขื˜ื•ืคื™ื ื‘ื”ื‘ื˜ื—ื” ืฉื ื“ื—ืชื”. ืขื ื–ืืช, ืคื•ื ืงืฆื™ื•ืช ืืกื™ื ื›ืจื•ืŸ ื™ื›ื•ืœื•ืช ืœื”ืฉืชืžืฉ ื‘- 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 ืชืกืชื™ื™ื ื‘-Undefined (ื›ืืฉืจ ืฉื•ื ื“ื‘ืจ ืœื ืžื•ื—ื–ืจ ื‘ื‘ืœื•ืง ื”-try) ืื• ืขื ืฉื’ื™ืื” ืฉื ืชืคืกื”. ื›ืชื•ืฆืื” ืžื›ืš, ืคื•ื ืงืฆื™ื” ื–ื• ืœื ืชื™ื›ืฉืœ ืžื›ื™ื•ื•ืŸ ืฉื”-try/catch ื™ื˜ืคืœ ื‘ืคื•ื ืงืฆื™ื” foo ืขืฆืžื”.

ื”ื ื” ืขื•ื“ ื“ื•ื’ืžื”:

async function foo() {
  try {
    return canRejectOrReturn();
  } catch (e) {
    return 'error caught';
  }
}

ื›ื“ืื™ ืœืฉื™ื ืœื‘ ืœืขื•ื‘ื“ื” ืฉื‘ื“ื•ื’ืžื”, canRejectOrReturn ืžื•ื—ื–ืจ ืž-foo. Foo ื‘ืžืงืจื” ื–ื” ืื• ืžืกืชื™ื™ื ืขื ืžืกืคืจ ืžื•ืฉืœื ืื• ืžื—ื–ื™ืจ ืฉื’ื™ืื” ("ืกืœื™ื—ื”, ืžืกืคืจ ื’ื“ื•ืœ ืžื“ื™"). ื—ืกื™ืžืช ื”-catch ืœืขื•ืœื ืœื ืชื‘ื•ืฆืข.

ื”ื‘ืขื™ื” ื”ื™ื ืฉ-foo ืžื—ื–ื™ืจื” ืืช ื”ื”ื‘ื˜ื—ื” ืฉื”ื•ืขื‘ืจื” ืž-canRejectOrReturn. ืื– ื”ืคืชืจื•ืŸ ืœ-foo ื”ื•ืคืš ืœืคืชืจื•ืŸ ืœ-canRejectOrReturn. ื‘ืžืงืจื” ื–ื”, ื”ืงื•ื“ ื™ื”ื™ื” ืžื•ืจื›ื‘ ืžืฉืชื™ ืฉื•ืจื•ืช ื‘ืœื‘ื“:

try {
    const promise = canRejectOrReturn();
    return promise;
}

ื–ื” ืžื” ืฉื™ืงืจื” ืื ืชืฉืชืžืฉ ื‘-await ื•ื—ื•ื–ืจ ื‘ื™ื—ื“:

async function foo() {
  try {
    return await canRejectOrReturn();
  } catch (e) {
    return 'error caught';
  }
}

ื‘ืงื•ื“ ืœืžืขืœื”, foo ืชืฆื ื‘ื”ืฆืœื—ื” ืขื ืžืกืคืจ ืžื•ืฉืœื ื•ื’ื ืขื ืฉื’ื™ืื” ืฉื ืชืคืกื”. ืœื ื™ื”ื™ื• ื›ืืŸ ืกื™ืจื•ื‘ื™ื. ืื‘ืœ foo ื™ื—ื–ื•ืจ ืขื canRejectOrReturn, ืœื ืขื undefined. ื‘ื•ื ื ื•ื•ื“ื ื–ืืช ืขืœ ื™ื“ื™ ื”ืกืจืช ืฉื•ืจืช return await canRejectOrReturn() :

try {
    const value = await canRejectOrReturn();
    return value;
}
// โ€ฆ

ื˜ืขื•ื™ื•ืช ื•ืžืœื›ื•ื“ื•ืช ื ืคื•ืฆื•ืช

ื‘ืžืงืจื™ื ืžืกื•ื™ืžื™ื, ืฉื™ืžื•ืฉ ื‘-Async/Await ืขืœื•ืœ ืœื”ื•ื‘ื™ืœ ืœืฉื’ื™ืื•ืช.

ื ืฉื›ื— ืžื—ื›ื”

ื–ื” ืงื•ืจื” ืœืขืชื™ื ืงืจื•ื‘ื•ืช ืœืžื“ื™ - ืžื™ืœืช ื”ืžืคืชื— ืœื”ืžืชื™ืŸ ื ืฉื›ื—ืช ืœืคื ื™ ื”ื”ื‘ื˜ื—ื”:

async function foo() {
  try {
    canRejectOrReturn();
  } catch (e) {
    return 'caught';
  }
}

ื›ืคื™ ืฉืืชื” ื™ื›ื•ืœ ืœืจืื•ืช, ืื™ืŸ ื”ืžืชื ื” ืื• ื—ื–ืจื” ื‘ืงื•ื“. ืœื›ืŸ foo ืชืžื™ื“ ื™ื•ืฆื ืขื undefined ืœืœื ืขื™ื›ื•ื‘ ืฉืœ ืฉื ื™ื™ื” ืื—ืช. ืื‘ืœ ื”ื”ื‘ื˜ื—ื” ืชืชืงื™ื™ื. ืื ื”ื•ื ื–ื•ืจืง ืฉื’ื™ืื” ืื• ื“ื—ื™ื™ื”, UnhandledPromiseRejectionWarning ืชื™ืงืจื.

ืคื•ื ืงืฆื™ื•ืช ืืกื™ื ื›ืจื•ืŸ ื‘ื”ืชืงืฉืจื•ื™ื•ืช ื—ื•ื–ืจื•ืช

ืคื•ื ืงืฆื™ื•ืช ืืกื™ื ื›ืจื•ืŸ ืžืฉืžืฉื•ืช ืœืขืชื™ื ืงืจื•ื‘ื•ืช ืœืžื“ื™ ื‘-.map ืื• .filter ื›ื”ืชืงืฉืจื•ืช ื—ื•ื–ืจืช. ื“ื•ื’ืžื” ืœื›ืš ื”ื™ื ื”ืคื•ื ืงืฆื™ื” fetchPublicReposCount(ืฉื ืžืฉืชืžืฉ), ื”ืžื—ื–ื™ืจื” ืืช ืžืกืคืจ ื”ืžืื’ืจื™ื ื”ืคืชื•ื—ื™ื ื‘- GitHub. ื ื ื™ื— ืฉื™ืฉ ืฉืœื•ืฉื” ืžืฉืชืžืฉื™ื ืฉืื ื—ื ื• ืฆืจื™ื›ื™ื ืืช ื”ืžื“ื“ื™ื ืฉืœื”ื. ืœื”ืœืŸ ื”ืงื•ื“ ืœืžืฉื™ืžื” ื–ื•:

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'];
}

ืื ื—ื ื• ืฆืจื™ื›ื™ื ื—ืฉื‘ื•ื ื•ืช ืฉืœ ืืจืคืช ืกืœืžืŸ, ืื•ืงื˜ื•ืงื˜, ื ื•ืจื•ื•ื™ื’. ื‘ืžืงืจื” ื–ื” ืื ื• ืขื•ืฉื™ื:

const users = [
  'ArfatSalman',
  'octocat',
  'norvig'
];
 
const counts = users.map(async username => {
  const count = await fetchPublicReposCount(username);
  return count;
});

ื›ื“ืื™ ืœืฉื™ื ืœื‘ ืœ-Await ื‘-.map callback. ื›ืืŸ ืกืคื™ืจืช ื”ื™ื ืžืขืจืš ืฉืœ ื”ื‘ื˜ื—ื•ืช, ื•-.map ื”ื•ื ื”ืชืงืฉืจื•ืช ืื ื•ื ื™ืžื™ืช ืขื‘ื•ืจ ื›ืœ ืžืฉืชืžืฉ ืฉืฆื•ื™ืŸ.

ืฉื™ืžื•ืฉ ืขืงื‘ื™ ืžื“ื™ ื‘- wait

ื ื™ืงื— ืืช ื”ืงื•ื“ ื”ื–ื” ื›ื“ื•ื’ืžื”:

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;
}

ื›ืืŸ ืžืกืคืจ ื”-repo ืžืžื•ืงื ื‘ืžืฉืชื ื” ื”ืกืคื™ืจื”, ื•ืื– ื”ืžืกืคืจ ื”ื–ื” ืžืชื•ื•ืกืฃ ืœืžืขืจืš ื”ืกืคื™ืจื•ืช. ื”ื‘ืขื™ื” ืขื ื”ืงื•ื“ ื”ื™ื ืฉืขื“ ืฉื”ื ืชื•ื ื™ื ืฉืœ ื”ืžืฉืชืžืฉ ื”ืจืืฉื•ืŸ ื™ื’ื™ืขื• ืžื”ืฉืจืช, ื›ืœ ื”ืžืฉืชืžืฉื™ื ื”ื‘ืื™ื ื™ื”ื™ื• ื‘ืžืฆื‘ ื”ืžืชื ื”. ืœืคื™ื›ืš, ืจืง ืžืฉืชืžืฉ ืื—ื“ ืžืขื•ื‘ื“ ื‘ื›ืœ ืคืขื.

ืื, ืœืžืฉืœ, ื–ื” ืœื•ืงื— ื‘ืขืจืš 300 ืืœืคื™ื•ืช ื”ืฉื ื™ื™ื” ืœืขื‘ื“ ืžืฉืชืžืฉ ืื—ื“, ืื– ืขื‘ื•ืจ ื›ืœ ื”ืžืฉืชืžืฉื™ื ื–ื” ื›ื‘ืจ ืฉื ื™ื™ื”; ื”ื–ืžืŸ ื”ืžื•ืฉืงืข ื‘ืื•ืคืŸ ืœื™ื ื™ืืจื™ ืชืœื•ื™ ื‘ืžืกืคืจ ื”ืžืฉืชืžืฉื™ื. ืืš ืžื›ื™ื•ื•ืŸ ืฉืงื‘ืœืช ืžืกืคืจ ื”-repo ืื™ื ื” ืชืœื•ื™ื” ื–ื” ื‘ื–ื”, ื ื™ืชืŸ ืœื‘ืฆืข ื‘ืžืงื‘ื™ืœ ืืช ื”ืชื”ืœื™ื›ื™ื. ื–ื” ื“ื•ืจืฉ ืขื‘ื•ื“ื” ืขื .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 ืžืงื‘ืœ ืžืขืจืš ื”ื‘ื˜ื—ื•ืช ื›ืงืœื˜ ื•ืžื—ื–ื™ืจ ื”ื‘ื˜ื—ื”. ื”ืื—ืจื•ืŸ, ืœืื—ืจ ืฉื”ื•ืฉืœืžื• ื›ืœ ื”ื”ื‘ื˜ื—ื•ืช ื‘ืžืขืจืš ืื• ื‘ื“ื—ื™ื™ื” ื”ืจืืฉื•ื ื”, ื”ื•ืฉืœื. ื™ื›ื•ืœ ืœืงืจื•ืช ืฉื›ื•ืœื ืœื ืžืชื—ื™ืœื™ื ื‘ื• ื–ืžื ื™ืช - ืขืœ ืžื ืช ืœื”ื‘ื˜ื™ื— ื”ืชื—ืœื” ื‘ื• ื–ืžื ื™ืช, ื ื™ืชืŸ ืœื”ืฉืชืžืฉ ื‘-p-map.

ืžืกืงื ื”

ืคื•ื ืงืฆื™ื•ืช ืืกื™ื ื›ืจื•ืŸ ื”ื•ืคื›ื•ืช ื™ื•ืชืจ ื•ื™ื•ืชืจ ื—ืฉื•ื‘ื•ืช ืœืคื™ืชื•ื—. ื•ื‘ื›ืŸ, ืขื‘ื•ืจ ืฉื™ืžื•ืฉ ืื“ืคื˜ื™ื‘ื™ ื‘ืคื•ื ืงืฆื™ื•ืช ืืกื™ื ื›ืจื•ืŸ ื›ื“ืื™ ืœื”ืฉืชืžืฉ ืื™ื˜ืจื˜ื•ืจื™ื ืืกื™ื ื›ืจื•ื ื™ื™ื. ืžืคืชื— JavaScript ืฆืจื™ืš ืœื”ื™ื•ืช ื‘ืงื™ื ื‘ื–ื”.

Skillbox ืžืžืœื™ืฆื”:

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”