繁体   English   中英

将回调函数的结果推入数组时如何等待迭代完成

[英]How to wait for the iteration to finish when pushing result of a callback function into an array

实现 array.push 的正确方法是什么,以便在 forEach 迭代完成后返回“array_of_results”?

const postgres = require("./postgres");

function get_array(value) {
    var array_of_results = []
    value.forEach( item => {
        postgres.query(item["id"],function(res){ 
            console.log(res) //gives proper res after empty array
            array_of_results.push(res);
        })
    });
    console.log(array_of_results)// prints empty array
    return array_of_results;
}

编辑:和 postgres.js 看起来像:

const { Pool } = require("pg");
const pool = new Pool();

var query_string = "select...."

function query(id, call) {
    pool.query(query_string, [id], (err, res) => {
        if (err) {
            console.log(err.stack)
        } else {
            call(res.rows[0])
        }
    })
}

module.exports = {
    query
}

有几种方法可以做到这一点,但首先你需要了解实际发生了什么。

postgres.query(item["id"],function(res){您使用 (1) 项目 ID 和 (2) 回调函数调用 postgres.query。该调用发生,然后立即在您的调用代码中继续。所以现在你刚刚向你的数据库发送了一堆请求,然后立即返回一个空数组。那些回调(2)还没有被调用。

要将数据返回到您的调用函数,您需要传递回调而不是使用return ,或者更改为 async/await。

在循环的每次迭代中使用 async/await 效率不高,因为您正在等待每个调用按顺序返回。 对于最有效的方法,您需要触发请求并等待它们全部完成。 您可以通过使用承诺来做到这一点。

您可以修改代码,为循环的每次迭代将承诺推送到数组中,然后在承诺数组上调用(并等待) Promise.all

这是为您进行的基本重写:

postgres.js:

function query(id) {
    return new Promise((resolve, reject) => {
        pool.query(query_string, [id], (err, res) => {
            if (err) {
                console.log(err.stack)
                reject(err)
            } else {
                resolve(res.rows[0])
            }
        })
    })
}

module.exports = {
    query
}

get_array 实现:

async function get_array(value) {
    var array_of_promises = [], array_of_results = []
    value.forEach( item => {
        array_of_promises.push(postgres.query(item["id"]));
    });
    array_of_results = await Promise.all(array_of_promises);
    console.log(array_of_results)// prints populated array
    return array_of_results;
}

请注意,当您调用get_array您必须在调用之前使用 await,例如将var array = get_array(items)更改为var array = await get_array(items)并且在函数中使用await需要将其声明为异步函数.

如果不能将其声明为异步函数,则可以更改调用代码以使用承诺:

var arrayPromise = get_array(items);
arrayPromise.then((results) => {
    // do something with results
    // but remember you cannot _return_ from within a callback, as discussed above
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM