我试图在承诺中执行for循环但没有成功,我认为我的问题与调用解析的位置有关,但我不确定
/*
* Get conversations of user
* @param user {String}
*/
function getConversations(user){
return new Promise(function(resolve, reject){
var conversations = user.Conversations
var newConversations = []
for(var conversation of conversations) {
helperGetConvo(conversation.ConversID).then(function(convo){
newConversations.push(createConversationObject({messages:[], name:convo.conversationName, users:["broulaye", "doumbia"], Id:convo.conversationID}))
}).catch(function(reason) {
console.log("failure when finding conversation 2: " + reason)
})
}
resolve(newConversations)
})
}
function helperGetConvo(convoId) {
return new Promise (function(resolve, reject){
query.findConversation(convoId).then(function(convers) {
if(convers) {
console.log("conversation was found: " + convers)
}
else {
console.log("conversation was not found: " + convers)
}
resolve(convers)
}).catch(function(reason) {
console.log("failure when finding conversation: " + reason)
})
})
}

当我执行这样的代码时,getConversations函数只返回一个空数组。但是当我像这样更改getConversations函数时:
function getConversations(user){
return new Promise(function(resolve, reject){
var conversations = user.Conversations
var newConversations = []
for(var conversation of conversations) {
helperGetConvo(conversation.ConversID).then(function(convo){
newConversations.push(createConversationObject({messages:[], name:convo.conversationName, users:["broulaye", "doumbia"], Id:convo.conversationID}))
resolve(newConversations)
}).catch(function(reason) {
console.log("failure when finding conversation 2: " + reason)
})
}
})
}

我确实得到了一个输出,但它没有通过整个forloop我相信,因为从我的理解解决工作就像一个返回声明。
有人帮助PLZ答案 0 :(得分:2)
您需要使用Promise.all
function getConversations(user){
var conversations = user.Conversations
var promises = conversations.map(c=>helperGetConvo(c.ConversID))
return Promise.all(promises)
.then(data=>{
let newConversations = data.map(convo=>{
return createConversationObject({messages:[], name:convo.conversationName, users:["broulaye", "doumbia"], Id:convo.conversationID})
})
return newConversations
})
.catch(reason=>{
console.log("failure when finding conversation: " + reason)
})
}
使用像这样的功能
getConversations(user).then(newConversations=>{
//your code
})
答案 1 :(得分:1)
一种方法是使用map而不是for-in来收集数组中的promise。然后使用Promise.all()等待所有这些解析(或拒绝一个)。
类似的东西:
mouse out
记住所有承诺必须解决或拒绝。如果你不遵守这条规则就会遇到麻烦。
答案 2 :(得分:1)
问题在于,当你致电resolve
时,你正在解决整个承诺。 for循环不等待每个helperGetConvo()
调用完成,然后再转到下一个调用。无论这些承诺中的哪一个首先发出then
声明,都会调用resolve
,这就是您的外部承诺将解决的问题。
您可以在Understanding promises in node.js了解有关承诺的更多信息。
如果您想等待一组承诺完成,请使用Promise.all
。它包含一个承诺列表,只有在所有承诺成功完成后才会解决。
function getConversations(user) {
return new Promise(function (resolve, reject) {
var conversations = user.Conversations;
var newConversations = [];
//create a list of promises
var promises = [];
for (var conversation of conversations) {
// push each promise into our array
promises.push(
helperGetConvo(conversation.ConversID).then(function (convo) {
newConversations.push(createConversationObject({
messages: [],
name: convo.conversationName,
users: ['broulaye', 'doumbia'],
Id: convo.conversationID
}));
}).catch(function (reason) {
console.log('failure when finding conversation 2: ' + reason);
})
);
}
// wait for all promises to complete
// when then do, resolve the newConversations variable
// which will now have all of the conversation objects that we wanted to create
Promise.all(promises).then(() => resolve(newConversations)).catch(reject);
});
}
你也可以使用async / await来清理它。 Async / await提供了一些很好的语法糖,无需执行return new Promise(...)
。下一个代码片段不是使用async / await的最佳方式,因为for循环将同步处理所有内容(一次一个会话)。这篇博文非常有助于我理解在迭代问题中使用async / await:https://blog.lavrton.com/javascript-loops-how-to-handle-async-await-6252dd3c795。
async function getConversations(user) {
var conversations = user.Conversations;
var newConversations = [];
// process each converstaion in sequence
for (var conversation of conversations) {
// instead of doing .then() we can use await
// convo will have the result from the helperGetConvo
// we put it in a try/catch because output
// we still want to have the error if something fails
try {
var convo = await helperGetConvo(conversation.ConversID);
newConversations.push(createConversationObject({
messages: [],
name: convo.conversationName,
users: ['broulaye', 'doumbia'],
Id: convo.conversationID
}));
} catch(reason) {
console.log('failure when finding conversation 2: ' + reason);
}
}
// return
return newConversations;
}
异步函数返回promise。所以你可以通过getConversations(user).then(...)
来调用这个函数。但我认为async / await使您的代码看起来更清晰。肯定会有进一步的优化,但希望这可以让你开始。
答案 3 :(得分:1)
你可以在我试图解决类似问题时找到的辅助函数中循环一个promise。我使用这种方法来循环承诺,因为它不会在第一个被拒绝的承诺中失败。相反,我可以处理解决方案或拒绝并在循环结束后返回最终结果。下面的代码段中的Promise使用bluebird,http://bluebirdjs.com/docs/getting-started.html
function promiseWhile(condition, action) {
return new Promise((resolve, reject) => {
var loop = () => {
if (!condition()) return resolve();
return Promise.cast(action())
.then(loop)
.catch(reject);
};
process.nextTick(loop);
return resolve;
})
}
我修改了一些虚拟数据提供的代码示例,并使其与辅助函数一起使用。因此,我相信你的getConversations函数看起来像这样:
function getConversations(user) {
var conversations = user.Conversations;
var newConversations = [];
var stop = conversations.length;
var index = 0
//loop promise
return promiseWhile(() => {
// Condition for stopping
return index < stop;
}, () => {
// Action to run, should return a promise
return new Promise((resolve, reject) => {
helperGetConvo(conversations[index].ConversID)
.then(function(convo) {
newConversations.push(createConversationObject({
messages: [],
name: convo.conversationName,
users: ['broulaye', 'doumbia'],
Id: convo.conversationID
}));
index++;
resolve();
})
.catch((error) => {
console.log('failure when finding conversation: ' + error);
index++;
resolve();
});
})
})
//This will execute when loop ends
.then(() => {
return newConversations;
});
}
希望这有帮助。