在异步代码的for循环完成后,如何解决此承诺?

时间:2018-07-20 08:58:11

标签: javascript for-loop asynchronous promise

在没有setTimeout的情况下,似乎无法弄清楚该如何工作。 我只想在异步PostgreSQL内容完成并且该映射包含它应该包含的所有键/值对之后,控制台记录我的映射。

const map = new Map();
pool.query(`SELECT * FROM trips WHERE destination = $1 AND begin_time >= $2 AND begin_time < $3 ORDER BY begin_time`, ['BROWNSVILLE ROCKAWAY AV', '2018-07-18 00:00-04:00', '2018-07-19 00:00-04:00'])
.then(res => {
    return new Promise((resolve, reject) => {
        const { rows } = res;
        resolve(rows);
    });
})
.then(res1 => {
    return new Promise((resolve, reject) => {
        for (let i = 0; i < res1.length; i++) {
            if (res1[i + 1]) {
                pool.query(`SELECT * FROM get_hwtable($1, $2)`, [res1[i].trip_id, res1[i + 1].trip_id]).then(res => {
                    const { rows: hwRows } = res;
                    map.set([res1[i].trip_id, res1[i + 1].trip_id], hwRows);
                }).catch(e => console.log('20', e));
            }
        }
        setTimeout(() => {
            resolve(map);
        }, 8000);
    });
})
.catch(e => console.log('25', e))
.finally(function () {
    console.log(map);
});

2 个答案:

答案 0 :(得分:0)

您可以简单地在Promise.all返回的承诺中使用pool.query

const map = new Map();
pool.query(`SELECT * FROM trips WHERE destination = $1 AND begin_time >= $2 AND begin_time < $3 ORDER BY begin_time`, ['BROWNSVILLE ROCKAWAY AV', '2018-07-18 00:00-04:00', '2018-07-19 00:00-04:00'])
.then(({rows}) => rows)
.then(res1 => Promise.all(res1.map((r, i) => {
    if (res1[i + 1]) {
        return pool.query(`SELECT * FROM get_hwtable($1, $2)`, [r.trip_id, res1[i + 1].trip_id])
        .then(res => {
            const { rows: hwRows } = res;
            map.set([res1[i].trip_id, res1[i + 1].trip_id], hwRows);
        }).catch(e => console.log('20', e))
    }                                 
})))
.catch(e => console.log('25', e))
.finally(function () {
    console.log(map);
});

答案 1 :(得分:0)

  1. 您的代码中没有不必要的构造。在第一个then( res => {..} )中, 无需返回Promise。你可以做

```

pool.query().then(res => {
    const {rows} = res;
    return rows;
}.then ....

```

  1. 如果您已经在使用async,则应该使用await并将其用于整个代码块。也可以编写一个承诺的超时功能。

```

///returns a promise that resolves after `duration`
function timeoutPromise(duration) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, duration)
  })
}

async function doSomething() {
  const res = await pool.query()
  const {rows} = res;
  for (...) {
    let hwRows = await pool.query(`SELECT * FROM get_hwtable($1, $2)`, [res1[i].trip_id, res1[i + 1].trip_id]);
    map...
  }
  await timeoutPromise(5000)
}

doSomething()

```

  1. 当然,以上内容可能会使用户等待太久,因为异步操作(let hwRows = await pool.query())将一步一步执行。使用Array.map返回Promise的数组,然后使用Promise.all([Promise])获取值。

```

async function doSomething() {
  const res = await pool.query()
  const {rows} = res;
  let hwRowsPromises = rows.map((row) => {
    // ...
    // return the promise
    return pool.query(`SELECT * FROM get_hwtable($1, $2)`, [res1[i].trip_id, res1[i + 1].trip_id])
  })
  let hwRowsResults = Promise.all(hwRowsPromises)
  await timeoutPromise(5000)
}

``` 4. Promise.all解析数组中的promise解析的值,因此您可以使用flatten之类的便捷方式来展平数组。

```

_.flatten([1, [2, [3, [4]], 5]]);
// => [1, 2, [3, [4]], 5]

```

参考