#javascript #node.js #json #promise #async-await
#javascript #node.js #json #обещание #async-await
Вопрос:
У меня есть следующий try/catch
блок, который выполняет 3 разных вызова api. Следующий код работает нормально, но его выполнение занимает много времени при firstData
наличии большого набора данных.
try {
const firstData = await myservice1.myservice1Func();
for(let i=0; i<firstData.total; i ){
const hostName = firstData.rows[i]['hostname'];
if (hostName !== null amp;amp; firstData.rows[i]['myservice1Id'] !== null) {
const aRes = await myService2(hostName);
firstData.rows[i]['mylist'] =
aRes[0].dataValues;
}
if (hostName !== null amp;amp; firstData.rows[i]['type'].includes('type1')) {
const oRes = await myService3(hostName);
firstData.rows[i]['ores'] = oRes.rows[0];
}
if (hostName !== null amp;amp; firstData.rows[i]['type'].includes('type2')) {
const vRes = await myService4(hostName);
firstData.rows[i]['vRes'] = vRes.rows[0];
}
}
return firstData;
} catch (err) {
console.log(err);
}
Здесь,
const firstData =
{
"total": 2,
"rows": [
{
"hostname": "abc.com",
"ipAddress": "11.11.11.11",
"myservice1Id": "ee0f77c9-ef15",
"type": "type1"
},
{
"hostname": "cde.com",
"ipAddress": "12.12.12.12",
"type": "type2",
"myservice1Id": null
}
]
}
const aRes =
[
{
"listType": "list1",
"createdAt": "2020-12-07"
}
]
const oRes =
{
"rows": [
{
"status": "FAIL"
}
]
}
const vRes =
{
"rows": [
{
"status": "FAIL"
}
]
}
Конечное firstData
возвращаемое значение выглядит следующим образом:
{
"total": 2,
"rows": [
{
"hostname": "abc.com",
"ipAddress": "11.11.11.11",
"myservice1Id": "ee0f77c9-ef15",
"type": "type1",
"oRes": {
"status": "PASS"
},
"mylist": {
"listType": "list1",
"createdAt": "2020-12-07"
}
},
{
"hostname": "cde.com",
"ipAddress": "12.12.12.12",
"type": "type2",
"myservice1Id": null,
"vRes": {
"status": "FAIL"
}
}
]
}
Здесь следует отметить, что все 3 if blocks
могут выполняться параллельно, потому что они независимы друг от друга.
Могу ли я использовать Promise.all
для выполнения всех 3 if blocks
parallel
-х входов?
Если да, то как будет выглядеть обновленный код при использовании Promise.all
?
Ответ №1:
Простейшей настройкой было бы поместить каждое обещание в массив внутри if
s:
const proms = [];
if (hostName !== null amp;amp; firstData.rows[i].myservice1Id !== null) {
proms.push(
myService2(hostName)
.then(aRes => firstData.rows[i].mylist = aRes[0].dataValues)
);
}
// other ifs changed around the same way
await Promise.all(proms);
Вы также могли бы упростить код hostName
, выполнив проверку только один раз, и похоже, что вы перебираете весь массив, что можно сделать проще, вызвав итератор:
try {
const firstData = await myservice1.myservice1Func();
for (const row of firstData.rows) {
const hostName = row.hostname;
if (hostName === null) continue;
const proms = [];
if (row.myservice1Id !== null) {
proms.push(
myService2(hostName)
.then(aRes => row.mylist = aRes[0].dataValues)
);
}
// etc
Комментарии:
1. не могли бы вы подсказать, где включить
for loop
?2. Там же, где он находится в вашем текущем коде. С кодом в ответе вы будете выполнять до 3 параллельных запросов, что довольно разумно, я бы не хотел выходить за рамки этого обычно, хотя это зависит от того, насколько параллелизм может обрабатывать служба.
3. В конце концов, что я должен делать
return proms;
?4. Нет, вам просто нужно
await Promise.all(proms);
, как в ответе, а затем после этого эта строка будет полностью заполнена5. Я получаю сообщение об ошибке
TypeError: Cannot read property 'dataValues' of undefined
, не могли бы вы сообщить мне, куда добавить эту проверку на неопределенный?
Ответ №2:
Привет, у вас есть небольшие изменения в коде,
for(let i=0; i<firstData.total; i ){
const hostName = firstData.rows[i]['hostname'];
//check if condition inside the service and return a null (a promise)
Promise.all([myService2(hostName), myService3(hostName), myService4(hostName)]).then((values) => {
console.log(values);
//[resutl1,null,result3]
});
}
Теперь проблема здесь в том, что вам нужно дождаться завершения самой медленной итерации,
Вы можете исправить это с помощью пула обещаний,
@supercharge/ promise-pool