Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
5
Help us understand the problem. What is going on with this article?
@atsumo

Promiseを複数の直列処理と並列処理を組み合わせる

More than 3 years have passed since last update.

そもそもそんな複雑なことしないほうが...
まあそうですね…

今回のタイミングで改めてPromiseやArrayまわりと向き合ったのでメモ

直列処理

const task = (label, timeout) => {
    return () => {
        return new Promise((resolve, reject) => {
            console.log(`${label} start`);

            setTimeout(() => {
                console.log(`${label} done`);
                //timeout秒経ったら次へ
                resolve();
            }, timeout);
        });
    }
};

console.log('promise start');
Promise.resolve()
    .then(task('task1', 100))
    .then(task('task2', 200));

こんな処理が3回とかだったらまだいいかもしれないが、これが多数となったらこのままthenで続けるような記述をするのはつらすぎる…

そこでArray#reduceを使って記述してみる
Array.prototype.reduce() - JavaScript | MDN

Array#reduceを使って直列繋ぎ

promise-reduce.js
const task = (label, timeout) => {
    return () => {
        return new Promise((resolve, reject) => {
            console.log(`${label} start time: ${timeout}`);

            setTimeout(() => {
                console.log(`${label} done`);
                //timeout秒経ったら次へ
                resolve();
            }, timeout);
        });
    }
};

const REPEAT = 10;
[...Array(REPEAT).keys()].reduce((promise, current) => {
    let label = `task${current}`;
  let timeout = Math.floor((Math.random() * 500));
    return promise.then(task(label, timeout));
}, Promise.resolve());

結果

$node promise-reduce.js

task0 start time: 69
task0 done
task1 start time: 5
task1 done
task2 start time: 191
task2 done
task3 start time: 89
task3 done
task4 start time: 458
task4 done
task5 start time: 112
task5 done
task6 start time: 107
task6 done
task7 start time: 14
task7 done
task8 start time: 284
task8 done
task9 start time: 183
task9 done

並列×直列処理

この個数が更に増えたら、ちょっとだけ並列にも動かしたい。
でも結果は同時にほしい

promise-parallel-serial.js
const task = (label, timeout) => {
  return () => {
    return new Promise((resolve, reject) => {
      console.log(`start: ${label}  time: ${timeout}`);

      setTimeout(() => {
        console.log(`done:  ${label}  time: ${timeout}`);
        //timeout秒経ったら次へ
        resolve();
      }, timeout);
    });
  }
};

//直列処理は3つ
const REPEAT = 3;
//並列は4つ
const PARALLEL = 4;

const parallels = [...Array(PARALLEL).keys()].map(index => {
  let lastpromise = [...Array(REPEAT).keys()].reduce((promise, current) => {
    let label = `task ${index+1}-${current+1}`;
    let timeout = Math.floor((Math.random() * 500));
    return promise.then(task(label, timeout));
  }, Promise.resolve());

  return lastpromise;
});


Promise.all(parallels).then(() => {
    //並列実行したすべてが完了したとき
  console.log('all done');
});

結果

start: task 1-1  time: 179
start: task 2-1  time: 26
start: task 3-1  time: 199
start: task 4-1  time: 303
done:  task 2-1  time: 26
start: task 2-2  time: 469
done:  task 1-1  time: 179
start: task 1-2  time: 365
done:  task 3-1  time: 199
start: task 3-2  time: 36
done:  task 3-2  time: 36
start: task 3-3  time: 360
done:  task 4-1  time: 303
start: task 4-2  time: 474
done:  task 2-2  time: 469
start: task 2-3  time: 331
done:  task 1-2  time: 365
start: task 1-3  time: 82
done:  task 3-3  time: 360
done:  task 1-3  time: 82
done:  task 4-2  time: 474
start: task 4-3  time: 47
done:  task 4-3  time: 47
done:  task 2-3  time: 331

メモ

  • Promise.allはthenをまとめてるだけ。
  • async/awaitのほうがわかりやすいだろうな

参考

5
Help us understand the problem. What is going on with this article?
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
atsumo

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
5
Help us understand the problem. What is going on with this article?