#javascript #node.js
#javascript #node.js
Вопрос:
Мне нужно выполнить цикл и дождаться измененного результата в конце await
вызова функции.
Что было бы лучшим вариантом дождаться всего выполнения и только после завершения цикла вернуть результат?
try {
for await (var [i, object] of tablesArchive.data.entries()) {
if (Object.keys(object).length === 0) {
continue;
}
// Busca IDs de relacoes existentes
await this.getIdByRalations(tablesArchive, object, async (newObject) => {
where = { [whereByProperty]: newObject[whereByProperty] };
// Atualiza ou cria o registro na base de dados
const registro = await this.upsertWithWhere(app, tablesArchive.modelName, where, newObject);
tablesArchive.data[i].id = registro.id;
});
}
} finally {
console.log('FINALLY ');
return tablesArchive.data;
}
В приведенном выше случае мне нужно изменить tablesArchive.data
объект и только после просмотра всех индексов и обновления информации. Я хочу вызвать return со всеми изменениями.
Комментарии:
1. Какое отношение к этому имеет try / finally?
2. Вы можете пропустить
try
/finally
и просто запустить цикл for, за которым следует код, который вы хотите запустить после цикла for .
Ответ №1:
Вы не нуждаетесь в этом строго. Ваше использование await уже заставляет код «ждать», пока он не будет завершен, чтобы выполнить последние 2 оператора.
Конкретный пример того, зачем вам может понадобиться finally, заключается в том, что в вашем try
блоке может возникнуть исключение, и вы хотите убедиться, что код в блоке finally всегда выполняется, исключение или нет.
Я не думаю, что это то, что вам нужно добавлять по умолчанию всякий раз, когда возникает вероятность возникновения исключения. Вопрос в том, что вы хотите сделать в случае исключения? Я думаю, что способ по умолчанию справиться с этим — позволить исключению генерировать и откатывать стек, и его поймает только первое, что может с ним что-то сделать.
Есть конкретный случай, когда мне всегда нужен блок finally, когда я делаю что-то, связанное с базой данных, в соединении, и мне нужно освободить соединение, независимо от того, было вызвано исключение или нет:
try {
const conn = pool.getConnection();
await conn.query('...');
await conn.query('...');
} finally {
// Always release, error or not
conn.release();
}
Приведенный выше блок кода достаточно распространен в моем исходном коде, но это только потому, что есть конкретная вещь, которую я хочу выполнить, независимо от того, происходит исключение или нет.
Комментарии:
1. Проблема в том, что я вызываю асинхронную функцию внутри for. Без finally try для выполнения узел не ожидает возврата … Только использование try окончательно решило мою проблему. Но мне нужны были другие мнения и способы решения проблемы.
2. @PedroFelipeEliasDeSouza похоже
getIdByRalations()
, что это функция в стиле обратного вызова. Можете ли вы преобразовать его в функцию, основанную на обещаниях? Это был бы мой подход.finally
здесь это не будет иметь значения.
Ответ №2:
Вы можете поместить try / catch внутри цикла for и в блок catch, просто зарегистрируйте ошибку. Затем он продолжит выполнение, и вы можете поместить свой оператор return сразу после цикла for .
for (var [i, object] of tablesArchive.data.entries()) {
try {
if (Object.keys(object).length === 0) {
continue;
}
// Busca IDs de relacoes existentes
await this.getIdByRalations(tablesArchive, object, async (newObject) => {
where = { [whereByProperty]: newObject[whereByProperty] };
// Atualiza ou cria o registro na base de dados
const registro = await this.upsertWithWhere(app, tablesArchive.modelName, where, newObject);
tablesArchive.data[i].id = registro.id;
});
} catch (e) {
console.log(e);
}
}
return tablesArchive.data;
Ответ №3:
Здесь взгляните на API Promise.all() .
Краткое резюме: вы предоставляете массив обещаний Promise.all() и ждете, пока все обещания в этом массиве не будут завершены.
В вашем примере я бы сделал это так:
var promises = []
for await (var [i, object] of tablesArchive.data.entries()) {
if (Object.keys(object).length === 0) {
continue;
}
// I changed this line here
// just push every async function to the promises array
promises.push(this.getIdByRalations(tablesArchive, object, async (newObject) => {
where = { [whereByProperty]: newObject[whereByProperty] };
// Atualiza ou cria o registro na base de dados
const registro = await this.upsertWithWhere(app, tablesArchive.modelName, where, newObject);
tablesArchive.data[i].id = registro.id;
}));
}
return await Promise.all(promises).then(() => {
console.log('All promises are finished')
return tablesArchive.data
}).catch(err => {
console.error('Error occured in Promises.all: ' err)
}).finally(() => {
console.log('All promises Finished')
})