#javascript #node.js #promise #centos8
#javascript #node.js #обещание #centos8
Вопрос:
Итак, я столкнулся с чем-то действительно странным, я создаю в цикле около 10 обещаний и добавляю их в массив, но после await Promise.all() в некоторых случаях приложение завершается без ошибок.
Я не могу поделиться исходным кодом, но приведенный ниже код имеет ту же проблему при запуске в CentoOS 8 с nodejs: nodejs.x86_64 1:10.21.0-3.module_el8.2.0 391 8da3adc6
const shell = require("shelljs");
require('events').defaultMaxListeners = 15;
const run = async () => {
await foo(DATA);
console.log("Logging1"); // Get's printed
await foo(OTHER_DATA_1);
console.log("Logging2"); // Get's printed
await foo(OTHER_DATA_2); // Usually at this level is where I no longer see the last log line
// Here is also where the script exists without error (I've attached process.onExit and beforeExit but both print code 0
console.log("More logging"); // Never get's printed
}
const foo = async (allData) => {
let promises = [];
for (const data of allData) {
const command = "ecs-cli ....."; // An AWS ECS command (takes around ~1 minute)
const myPromise = new Promise((resolve, reject) => {
const cmdChildProcess = shell.exec(command, { silent: false, async: true });
cmdChildProcess.on("close", (code) => {
if (code === 0) {
const someData = doSomething(data);
console.log("Success!"); // Get's called
resolve(someData);
} else {
console.error(`Process forcibly exited with code ${code}`); // Haven't seen this log line
reject(code);
}
});
}).catch(error => {
console.log(error); // Haven't seen this get called either
});
promises.push(myPromise);
}
await Promise.all(promises);
console.log("I'm done with all the promises"); // Get's processed first couple of times
}
run();
Я не уверен, что я делаю не так, или это потому, что я увеличил количество прослушиваний.
Перед его увеличением я делал что-то вроде:
let promises = [];
...
//loop
promises.push(myPromise);
if(promises.length >= 6) {
await Promise.all(promises);
promises = [];
}
...
Но это не имело никакого значения, возникла та же проблема.
Заранее спасибо за всю помощь!
Комментарии:
1. Может быть, вы можете добавить a
setTimeout(()=>reject("timeout"), 50000)
для принудительного отклонения через некоторое время2. ох… попробуйте
run().then(() => console.log('fini'));
— я, кажется, вспоминаю, что node.js плевать на ожидающие обещания перед выходом3. @Sarabadu — прочитайте код …. команда занимает около 1 минуты — зачем вам принудительно отклонять через 50 секунд: p
4. @Bravo вы правы
setTimeout(()=>reject("timeout"), 120000)
, это лучше, но это тоже не очень хорошее решение, я буду использовать его только для тестирования. и было бы неплохо взглянуть, может лиecs-cli
команда запрашивать ожидание взаимодействия с пользователем или подтвердить какое-либо действие.5. @Sarabadu — Я сомневаюсь, что это как-то связано с тем, что обещания не завершаются — это node.js поведение — оно просто не ждет обещаний перед выходом — со мной такое случалось
Ответ №1:
Возможно, я обнаружил проблему, хотя я все еще не уверен на 100%, почему это проблема.
Но в принципе, если я сделаю следующее, это сработает:
for (const data of allData) {
const command = "ecs-cli ....."; // An AWS ECS command (takes around ~1 minute)
const myPromise = new Promise((resolve, reject) => {
const cmdChildProcess = shell.exec(command, { silent: false, async: true });
cmdChildProcess.on("close", (code) => {
if (code === 0) {
resolve({});
} else {
console.error(`Process forcibly exited with code ${code}`); // Haven't seen this log line
reject(code);
}
});
}).then((data) => {
doSomething(data); // Noy async
})
.catch(error => {
console.log(error); // Haven't seen this get called either
});
promises.push(myPromise);
}
await Promise.all(promises);
Как показано выше, в основном все, что я сделал, это удалил doSomething(data)
событие из onClose
события и привязал его как разрешение к обещанию, then()
и, похоже, теперь это работает.
Комментарии:
1. Какое возвращаемое значение
doSomething
? Возможно, это вызывало исключения?2. Я никогда не видел исключения, и это сообщение об успехе или сбое, но без исключений (оно вызывает AWS через их SDK)