[英]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.