Help us understand the problem. What is going on with this article?

bluebird.jsのPromise.mapとPromise.mapSeries

はじめに

この記事はbluebird.jsPromise.mapPromise.mapSeriesについて、株式会社OKANの社内勉強会で取り上げたものです。

1. Promise.mapについて

Promise.mapの公式ドキュメント

1-1. 概要

入出力仕様

Promise.map(array, function, options) -> Promise

map は第1引数で受け取る配列の各要素について、第2引数でそれを引数にとる非同期関数を 『並列に順番に実行して』、実行した全ての非同期関数の完了を待つPromiseを返す。

このPromiseがresolveしたとき、非同期関数の戻り値の結果が『順番に入った配列』を返す。ただし 『実行が完了する順番は保証されない』

つまり・・・

  • 結果の順番は保証される
  • 実行を開始する順番は保証される
  • 実行が完了する順番は保証されない

また、第3引数にconcurrencyプロパティを渡すと、同時に実行する数を制限できる(デフォルトは制限なし)。

1-2. サンプルコード

基本的な例

// 非同期的に2倍する関数
const x2 = num => {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(num * 2), 1000);
  });
};

const result = await Promise.map( [1, 2, 3, 4, 5], x2 );
console.log(result);
// -> [2, 4, 6, 8, 10]

実行完了の順番が保証されない例

// 非同期的かつランダムに遅らせて2倍する関数
const x2 = num => {
  return new Promise((resolve, reject) => {
    const ms = Math.random() * 1000 // ランダムな遅れ
    setTimeout(() => {
      const res = num * 2;
      console.log(res); // コンソール出力(処理完了)
      resolve(res);
    }, ms);
  });
};

const result = await Promise.map( [1, 2, 3, 4, 5], x2 );
console.log(result);
/*
# コンソール出力
> 10
> 6
> 8
> 2
> 4
# ↑のようなときもあれば

# ↓のようなときもある
> 2
> 10 
> 4
> 6
> 8

# だけどresultの値は必ず順番通りになる
> [2, 4, 6, 8, 10]
*/

concurrencyで同時に実行する数を制限する例

// 非同期的に2倍する関数
const x2 = num => {
  return new Promise((resolve, reject) => {
    setTimeout(() => resolve(num * 2), 1000);
  });
};

const result = await Promise.map([1, 2, 3, 4, 5], x2, { concurrency: 2 }); // 同時に2つ実行
console.log(result);

/*
# 出力
# 1秒後
> 1
> 2
# さらに1秒後
> 3
> 4
# さらに1秒後
> 5
# resultの値
> [2, 4, 6, 8, 10]
*/

2. Promise.mapSeriesについて

Promise.mapSeriesの公式ドキュメント

2-1. 概要

入出力仕様

Promise.mapSeries(array, function) -> Promise

mapSeriesは第1引数で受け取る配列の各要素について、第2引数でそれを引数にとる非同期関数を
『直列に順番に実行して』、実行した全ての非同期関数の完了を待つプロミスを返す。

Promise.mapと殆ど同じだが、唯一の違いは『実行が完了する順番が保証されること』。また、直列に実行するためconcurrencyプロパティがない。

2-2. サンプルコード

実行完了の順番が保証される例

// 非同期的かつランダムに遅らせて2倍する関数
const x2 = num => {
  return new Promise((resolve, reject) => {
    const ms = Math.random() * 1000 // ランダムな遅れ
    setTimeout(() => {
      const res = num * 2;
      console.log(res); // コンソール出力(処理完了)
      resolve(res);
    }, ms);
  });
};

const result = await Promise.mapSeries( [1, 2, 3, 4, 5], x2 );
console.log(result);

/*
# 出力
# 直列に実行するため処理が完了する順番が保証される
> 2 
> 4
> 6
> 8
> 10
# resultの値
> [2, 4, 6, 8, 10]
*/

3. 最後に

bluebird.js は便利なヘルパーが多数用意されていてとても便利ですね。非同期処理の実装がとてもラクになります。
Googleで調べるときは検索窓にbluebird.jsと入れることをオススメします。.jsをつけないで検索すると・・・。

horiuchie
株式会社OKAN / JavaScript, React, React Native, Ramda.js, AWS, Python / パンダが好き / 🐼PANDA(Positive ANalytic aDAptive)/ 和歌山 / ENTJ型 / Backlog
https://www.wantedly.com/users/125262687
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした