簡體   English   中英

將 then 的值保存在 Promise 之外的變量中

[英]Save value of then in a variable outside of the Promise

我對 Promises 的概念還很陌生,我試圖了解范圍是如何工作的。 我基本上是在嘗試將then()內部的值存儲到Promise外部的變量中

下面是我在 Nodejs (Express) 中編寫的一個簡單函數,使用 Sequelize 在數據庫上運行查詢。

exports.getTest = (req, res, next) => {
    var categories = [];
    var names = ['Category 1', 'Category 2', 'Category 3', 'Category 4'];
    for (var i = 0; i < names.length; i++) {
        model.Category.findOne({
            where: {
                name: names[i]
            },
            attributes: ['id']
        }).then(id => {
            categories.push(
            {
                category_id: id.id
            });
        });
    }
    res.json(categories);
}

之后我還有其他邏輯要運行,並且我有一個圍繞 Promise 的 for 循環。 所以,我不能在 then 中運行我的下一個邏輯,否則我會因為 for 循環而多次運行它。 我需要填充數組類別以在我的下一個操作中使用它。

目前,我的回復( res.json(categories) )是[]

任何幫助,將不勝感激。

PS:我知道這是一個常見的話題,但正如我所提到的,我對此還很陌生,其他答案不符合我的情況,讓我更加困惑。

提前致謝!

在您的情況下, categories將始終返回[]因為您不會在返回響應之前等待所有承諾完成。 For 循環在繼續下一次迭代之前不會等待異步操作完成。 因此循環結束,並且在它們中的任何一個完成之前返回響應。

與其在 for 循環中調用 promise,您應該將它們推送到一個數組中,然后您可以將其傳遞給Promise.all()函數。

這是它應該是什么樣子

exports.getTest = () => {
    var categories = [];
    var names = ['Category 1', 'Category 2', 'Category 3', 'Category 4'];
    var promiseArray = [];
    for (var i = 0; i < names.length; i++) {
        promiseArray.push(
          model.Category.findOne({
              where: {
                  name: names[i]
              },
              attributes: ['id']
          }).then(id => {
              categories.push(
              {
                  category_id: id.id
              });
          });
        )
    }

    return Promise.all(promiseArr)
}

getTest()現在返回一個 promise,因此可以像這樣調用它

getTest()
  .then(data => {
    // data will be an array of promise responses
  }).catch(err => {
    console.log(err);
  })

你可以試試 Promise.all()

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Promise.all() 方法返回一個 Promise,當所有作為可迭代傳遞的承諾都已解決或可迭代不包含任何承諾時,該 Promise 會解決。 它以第一個拒絕的承諾的原因拒絕。

 var getTest = (req, res, next) => { var categories = []; var promises = []; var names = ['Category 1', 'Category 2', 'Category 3', 'Category 4']; var resolveCount = 0; for (var i = 0; i < names.length; i++) { // Store the name in variable so that can be persistent and not // affected by the changing 'i' value const name = names[i] promises.push(new Promise((resolve, reject) => { // Your DB calls here. We shall use a simple timer to mimic the // effect setTimeout(() => { categories.push(name) resolveCount++; resolve(); }, 1000) })); } Promise.all(promises).then(function() { console.log("This should run ONCE before AFTER promise resolved") console.log("resolveCount: " + resolveCount) console.log(categories); // Do your logic with the updated array // res.json(categories); }); console.log("This will run immediately, before any promise resolve") console.log("resolveCount: " + resolveCount) console.log(categories) } getTest();

exports.getTest = (req, res, next) => {
    var categories = [];
    var names = ['Category 1', 'Category 2', 'Category 3', 'Category 4'];
    names.forEach(name => {
        Category.findOne({where: {name: name}}).then(category => {
            categories.push({category_id: category.id})
        })
    })
    res.json(categories);
}

所以基本上,model.findeOne() 返回一個帶有每個名稱的第一個類別的對象的承諾。 then() 捕獲該承諾,解決它,然后給它一個回調函數,該函數將該對象作為參數傳遞。

它可能看起來像

Categories.findOne({where: {name: name}).then(function(category){
    // do something with that category
})

但是箭頭函數使它更具可讀性,因為 then(category => {//some code})。

暫無
暫無

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

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