簡體   English   中英

NODE JS:如何進行以下調用等待被調用的 function 完成后再繼續

[英]NODE JS: How can I make the following call wait for the called function to finish before proceeding

我仍然無法將注意力集中在 async/await 功能上,並且針對以下情況嘗試了幾種解決方案,但均未成功:

我有這個 function:

function addDataToDb(articleData) {

    initMongoDb();

    kanpionDb.on('error', console.error.bind(console, 'connection error:'));
    kanpionDb.once('open', function () {
        SiteUrlModel.init().then(() => {
            articleData.forEach(articleItem => {
                var article = new SiteUrlModel(articleItem).save(function (error) {
                    if (error) {
                        console.log("Failed: " + articleItem.siteName);
                    } else {
                        console.log("Success " + articleItem.siteName);
                    }
                });
            });
        });
    });
}

從另一個文件中調用它:

c.on('drain', async function () {
    Database.addDataToDb(ArticleList);
    console.log("All done");
});

問題:如何使console.log("All done")僅在Database.addDataToDb(ArticleList)完成執行后顯示消息?

這個解決方案有點混亂,因為你有大量的異步技術混合在同一個 function 中:事件、承諾和回調,然后最重要的是,有一個循環。 這確實是一團糟,通常是您想要避免的。

這種復雜程度的最佳整體解決方案是備份幾個步驟,並承諾所有基本異步操作比這高幾個步驟。 對於您的數據庫,您應該 go 找到並使用 promise 接口到數據庫。 對於您的事件,由於這些都是一次性事件,您可以在 object 上構建 promise 包裝器,以獲取有關打開和錯誤事件的通知。

但是,由於我不知道您正在使用的所有組件,因此我無法真正為您完成這部分工作。 因此,我們將看看我們可以做些什么來將適當的 Promise 級別的支持修補到這種混合技術中。

const {promisify} = require('util');

function addDataToDb(articleData) {
    return new Promise((resolve, reject) => {
        initMongoDb();

        kanpionDb.on('error', err => {
            console.error('connection error:', error);
            reject(error);
        });
        kanpionDb.once('open', function () {
            SiteUrlModel.init().then(() => {
                return Promise.all(articleData.map(articleItem => {
                    let model = new SiteUrlModel(articleItem);
                    model.savePromise = promisify(model.save);
                    return model.savePromise().then(() => {
                        console.log("Success " + articleItem.siteName);
                    }).catch(err => {
                        console.log("Failed: " + articleItem.siteName);
                        throw err;
                    });
                }));
            }).then(resolve, reject);
        });
    });
}

// usage:
addDataToDb(articleData).then(() => {
    console.log("All Done");
}).catch(err => {
    console.log(err);
});

技術總結:

  1. 由於這些事件,我們必須將手動創建的 promise 包裝起來,完成后我們會解決或拒絕它。
  2. .forEach()循環被Promise.all(articleData.map(...))替換,這將給我們一個 promise 告訴我們所有保存何時完成。
  3. .save(callback)必須替換為.save()的承諾版本。 理想情況下,您只需在此處使用數據庫接口的承諾版本,但我已經展示了如何在必要時手動承諾.save() function。
  4. 將拒絕連接到error事件。
  5. 將解析和拒絕連接到SiteUrlModel.init() promise。
  6. Promise.all() promise 鏈接到SiteUrlModel.init() promise。

如果你可以請試試這個,

const saveData = (articleItem) => {
  return new Promise((resolve, reject) => {
     var article = new SiteUrlModel(articleItem).save(function (error) {
        if (error) {
           console.log("Failed: " + articleItem.siteName);
           reject(error);
        } else {
           console.log("Success " + articleItem.siteName);
           resolve('Success');
        }
     });
  });
});

const addDataToDb = (articleData) => {
  const list = [];
  return new Promise((resolve, reject) => {
    initMongoDb();

    kanpionDb.on('error', console.error.bind(console, 'connection error:'));
    kanpionDb.once('open', function () {
      SiteUrlModel.init().then(() => {
        articleData.forEach(articleItem => {
          list.push(saveData(articleItem);
        });
      });
    });

    Promise.all(list).then(response => {
      resolve(response);
    }).catch(error => {
      reject(error);
    })
  });
};

c.on('drain', async function () {
  const result = Database.addDataToDb(ArticleList).then(res => {
    console.log("All done");
  });
});

我正在嘗試使用香草承諾

您可以使用承諾讓調用者等待您的異步代碼完成。 重構您的addDataToDb function 以返回 promise 並相應地解析/拒絕 promise。 由於您已將“drain”回調定義為異步 function,因此您可以在回調中使用await關鍵字以使事情更簡潔:

c.on('drain', async function () {
    await Database.addDataToDb(ArticleList);
    console.log("All done");
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM