しがないエンジニアのブログ

技術的な内容をメモ代わりにつらつら

javascriptのPromiseやasync/awaitについて

Promise

Promiseはjs側で用意されている非同期処理である。

Promise.resolve().then(() => {
  console.log('1');
  return '1';
}).then((result) => {
  console.log('2');
  return result + '2';
}).then((result) => {
  console.log('3');
  return result + '3';
}).then((result) => {
  console.log('4');
  return result + '4';
}).then((result) => {
  console.log('5');
  return result + '5';
}).then((result) => {
  console.log(result);
});

/* => output
1
2
3
4
5
12345
*/

メソッドチェーンによって、段階的に処理を記述できる

jQuery.Deferred

DeferredはjQuery側のPromiseである。
例として、以下のサンプルを示す

const deferred = new $.Deferred();

setTimeout(() => {
  console.log('timeout 1000');
  deferred.resolve('resolved');
}, 1000);

deferred.promise().then((result) => {
  console.log(result);
});

/* => output
timeout 1000
promise
*/

となる。

deferred.resolve()で処理が終了したことを知らせて、
deferred.promise()で終了したデータを取得する。
resolve()に引数を渡すことで、promise()側でそのデータを利用できる

async/await

今風の一番いい書き方がこれ
async/awaitを使うことで、非同期をシーケンスに書くことができるようになる。
asyncを定義した関数内で、awaitを使用することができる。
awaitは、Promiseの結果を受け取る。awaitの指定した関数が終了するまで、処理が一時停止する。

IEではサポートされていないなど、ブラウザに制限がある(2019.3現在)
確認はこちらから

以下に例を示す

async function func(){
  const res1 = await afunc1();
  const res2 = await afunc2();
  const res3 = await afunc3();

  console.log('sum: ' + (res1 + res2 + res3));
}

// そのまま結果を返す(resolveされる)
function afunc1() {
  console.log(100);
  return 100;
}

// Promiseを宣言し、内部でresolveする
function afunc2() {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(200);
      resolve(200);
    }, 1000);
  });
}

// asyncを組み合わせてresolveする
async function afunc3() {
  await new Promise((resolve) => setTimeout(resolve, 2000));
  console.log(300);
  return 300;
}

func();

/* => output
100
200
300
sum: 600
*/

ちなみに、Promise.allというものを利用すれば、複数の処理を並列に行うことができる

async function func() {
  let promises = [];
  promises.push(subfunc('promise1', 1000));
  promises.push(subfunc('promise2', 2000));
  promises.push(subfunc('promise3', 500));

  const result = await Promise.all(promises);
}

function subfunc(name, ms) {
  console.log(name + ' start');
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log(name + ' resolve');
      resolve(name);
    }, ms);
  });
}

/* => output
promise1 start
promise2 start
promise3 start
promise3 resolve
promise1 resolve
promise2 resolve
*/


参考文献

Promise

Deferred

async/await