LoginSignup
6
5

More than 5 years have passed since last update.

非同期処理を含むループを同期処理

Posted at

目的

Promise.allで取得してきたものを順番を崩さずにDBに登録したい。

詰まったところ

forEachばかり使っていたので少しはまりました。
forEachはbreakもcontinueも使えないので更に使いどころを気にしようと思います。

非同期処理を含むループを同期処理したい場合はforEachは使えない。

forEachは引数がcallbackになるのでcallback内でawaitを使用するとasync functionではないのでSyntaxError

callback内をasync functionに変えて実行したらcallbackが非同期になるのでループが非同期になってしまう。
なのでfor系の文を使うしかない。

コード

test.js
const _ = require('underscore');
const knex = require('knex')({
  client: 'mysql',
  connection: {
    host : '127.0.0.1',
    user : 'root',
    password : 'password',
    database : 'database'
  }
});

(async () => {

  const nameList = [
    'name1',
    'name2',
    'duplicate',
    'name3',
    'name4',
    'name5',
    'name6',
    'name7',
    'name8',
    'duplicate',
    'name9',
    'name10',
  ];

  for (let index = 0; index < nameList.length; index++) {

    await sleep(1000);
    console.log(index);

    const name = nameList[index];

    // ループの前でwhere inでチェックするところですが無駄にSQLを投げています。
    const duplicateObject = await knex.select('*').from('test').where({
      name: name
    });

    if (! _.isEmpty(duplicateObject)) {
      continue;
    }

    await knex('test').insert({
      name: name,
    });

    console.log(name);

  }

  await knex.destroy();// コネクションを破棄しないとプロセスが終わらない

})().catch((error) => {
    console.log(error);
    process.exit(1);
});

function sleep(milliSeconds) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, milliSeconds);
  });
}

実行結果

node test.js

0
name1
1
name2
2
duplicate
3
name3
4
name4
5
name5
6
name6
7
name7
8
name8
9
10
name9
11
name10
mysql> select * from test;
+----+-----------+---------------------+---------------------+-----------------+-------------+
| id | name      | update_datetime     | create_datetime     | delete_datetime | delete_flag |
+----+-----------+---------------------+---------------------+-----------------+-------------+
|  1 | name1     | 2018-10-07 02:10:47 | 2018-10-07 02:10:47 | NULL            |           0 |
|  2 | name2     | 2018-10-07 02:10:48 | 2018-10-07 02:10:48 | NULL            |           0 |
|  3 | duplicate | 2018-10-07 02:10:49 | 2018-10-07 02:10:49 | NULL            |           0 |
|  4 | name3     | 2018-10-07 02:10:51 | 2018-10-07 02:10:51 | NULL            |           0 |
|  5 | name4     | 2018-10-07 02:10:52 | 2018-10-07 02:10:52 | NULL            |           0 |
|  6 | name5     | 2018-10-07 02:10:53 | 2018-10-07 02:10:53 | NULL            |           0 |
|  7 | name6     | 2018-10-07 02:10:54 | 2018-10-07 02:10:54 | NULL            |           0 |
|  8 | name7     | 2018-10-07 02:10:55 | 2018-10-07 02:10:55 | NULL            |           0 |
|  9 | name8     | 2018-10-07 02:10:56 | 2018-10-07 02:10:56 | NULL            |           0 |
| 10 | name9     | 2018-10-07 02:10:58 | 2018-10-07 02:10:58 | NULL            |           0 |
| 11 | name10    | 2018-10-07 02:10:59 | 2018-10-07 02:10:59 | NULL            |           0 |
+----+-----------+---------------------+---------------------+-----------------+-------------+
6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5