Остановка скрипта без ошибок после await Promise.all(…)

#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)