Как дождаться окончания итерации до 1000 * при загрузке результата функции обратного вызова в массив - PullRequest
0 голосов
/ 10 февраля 2020

Как правильно реализовать array.pu sh, чтобы его "array_of_results" возвращалось после итерации forEach, если она завершена?

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
}

1 Ответ

0 голосов
/ 10 февраля 2020

Есть несколько способов сделать это, но сначала вам нужно понять, что на самом деле происходит.

В postgres.query(item["id"],function(res){ вы звоните postgres .query с (1) идентификатором элемента и ( 2) функция обратного вызова. Этот вызов происходит, а затем немедленно продолжается в вашем коде вызова. Итак, вы только что отправили кучу запросов в вашу базу данных, а затем сразу же вернули пустой массив. Эти обратные вызовы (2) еще не были вызваны.

Чтобы вернуть данные в вызывающую функцию, вам нужно либо передать обратный вызов вместо использования return, либо перейти на асинхронное / ожидание.

Использование async / await на каждой итерации вашего l oop не так эффективно, так как вы ожидаете последовательного возврата каждого вызова. Для наиболее эффективного способа вам нужно будет запустить запросы и дождаться их завершения. Вы можете сделать это, используя обещания.

Вы можете изменить свой код на pu sh обещание в массив для каждой итерации l oop, затем вызвать (и ожидать) Promise.all на массив обещаний.

Вот базовый c переписать для вас:

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 в функции требует, чтобы она была объявлена ​​как асинхронная c function.

Если вы не можете объявить ее как асинхронную c функцию, вы можете изменить вызывающий код, чтобы использовать обещание:

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