В node.js почему мой Promise.all не видит мой массив обещаний, созданных моим предшественником для l oop? - PullRequest
0 голосов
/ 28 января 2020

Моя цель - провести oop через массив объектов и добавить их в базу данных MongoDB, если этот объект еще не существует внутри базы данных. Я хочу, чтобы мой код ждал, пока все объекты не будут добавлены, прежде чем двигаться дальше, поэтому я добавил функцию Promise.all и добавил любые функции insertOne в массив обещаний, называемых «обещания».

//Loop through currentActiveMarkets, add any insertOne requests to promises array
var promises = [];
for (let market of currentActiveMarkets){
    console.log("   Looking to see if marketHash exists: " + market.marketHash)
    //Search if marketHash already exists in MongoDB
    dbo.collection("bettingmarkets").findOne({ marketHash: market.marketHash }, function(err, exists) { 
        if (err) throw err;
        //if currentActiveMarkets is found in MongoDB already, do nothing
        if (exists) {
            console.log("   marketHash " + market.marketHash + " exists") 
        //if currentActiveMarkets is not found in MongoDB, insert it by adding to promise list
        } else { 
            console.log("   marketHash doesn't exist")
            var promise = new Promise(function(resolve, refuse){
                dbo.collection("bettingmarkets").insertOne(market, function(err, res) {
                    if (err) throw err;
                    console.log("   marketHash added to MongoDB: " + market.marketHash);
                    return resolve;
                })
            })
            //logging confirms promises are being added to promises array
            console.log("promise: " + promise);
            promises.push(promise);
            console.log("promises: " + promises);
        };
    });
};
Promise.all(promises).then(() => {
    console.log("   All non-duplicate ActiveMarkets have been added to MongoDB.");
    console.log(promises)// why are no promises making it into this Promise All array????
    })
    .catch((e) => {
        console.log("   Error with Promise All: " + e);
    });

Проблема в том, что Promise.all, по-видимому, выполняется до того, как что-либо будет выполнено внутри для l oop. Журналы показывают пустой массив обещаний == [] при запуске Promise.all.

Внутри фактического для l oop журналы показывают, что мои объекты обещаний добавляются в массив обещаний каждый раз, когда вызывается insertOne, но, как я уже сказал, Promise.all не видит их в массив. Promise.all выполняется до того, как обещания добавляются в массив обещаний.

Как я могу изменить свой код так, чтобы Promise.all (обещания) не выполнялся до тех пор, пока не будет завершено выполнение для l oop и обещания были добавлены в массив обещаний?

Ответы [ 2 ]

0 голосов
/ 28 января 2020

Ваш массив обещаний не заполняется вовремя, потому что вы пытаетесь заполнить его из асинхронного обратного вызова.

const timeout = delay => new Promise(r => setTimeout(r, delay));
const dummy = word => timeout(1000).then(() => word);

{
  const promises = [];
  timeout(1000).then(() => {
    // Too late!
    promises.push(dummy("hello"));
  });
  Promise.all(promises).then(p => {
    console.log(`First: ${p}`);
  });
}

{
  const promises = [];
  // On time
  promises.push(
    timeout(1000).then(() => dummy("hello"))
  );
  Promise.all(promises).then(p => {
    console.log(`Second: ${p}`);
  });
}

Драйвер Mon go поддерживает асинхронное / ожидание. Попробуйте написать это так:

const promises = currentActiveMarkets.map(async market => {
    console.log("   Looking to see if marketHash exists: " + market.marketHash)

    const bettingMarkets = dbo.collection("bettingmarkets")

    //Search if marketHash already exists in MongoDB
    const exists = await bettingMarkets.findOne({ marketHash: market.marketHash });

    //if currentActiveMarkets is found in MongoDB already, do nothing
    if (exists) {
        console.log("   marketHash " + market.marketHash + " exists") 
        return;
    }

   //if currentActiveMarkets is not found in MongoDB, insert it by adding to promise list
   console.log("   marketHash doesn't exist")

   const res = await bettingMarkets.insertOne(market)
   console.log("   marketHash added to MongoDB: " + market.marketHash);

   return res;
});

Promise.all(promises).then(() => {
    console.log("   All non-duplicate ActiveMarkets have been added to MongoDB.");
    console.log(promises)// why are no promises making it into this Promise All array????
    })
    .catch((e) => {
        console.log("   Error with Promise All: " + e);
    });
0 голосов
/ 28 января 2020

Если посмотреть на ваш код, я бы сказал, что проблема в следующем: dbo.collection("bettingmarkets").findOne().

Этот код асинхронный. Это означает, что он, вероятно, запустится после того, как вы закончили с for-l oop.

MongoDB немного неоднозначно в своей документации о db.collection.findOne () , но если она совпадает с этой документацией , вы можете использовать Обещание вместо обратных вызовов.

В этом случае вы можете использовать Array.prototype.map для заполнения массива (аналогично ответу Антино).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...