我有一个名为previewMessages
的数组,我需要遍历一个对象messages
,并获得一堆值。其中一个值需要异步调用,当然如果我想在for循环后使用previewMessages
变量,这将无法工作,例如对它进行排序。
以下是代码:
var displayMessages = function(messages) {
let previewMessages = [];
for (let messageID in messages) {
let message = messages[messageID];
let messageObj = {};
Promise.resolve(getItemsById([message.context.itemID])).then(function(itemInfo) {
messageObj.title = itemInfo[Object.keys(itemInfo)[0]].title;
});
previewMessages.push(messageObj);
}
}
我无法promise.all
,因为需要迭代消息,我需要异步调用来获取标题。
如果这有帮助,这是第一个调用上述函数的函数:
var getUserMessages = function(id) {
usersRef.child(`${id}/chats/`).on('value', function(snapshot) {
displayMessages(snapshot.val());
})
}
答案 0 :(得分:2)
两种替代方案:
如果异步调用可以并行运行(即使可能有100个,也没关系),你可以使用Promise.all
:
let previewMessages = [];
let promises = [];
// Build the array of promises
for (let messageID in messages) {
let message = messages[messageID];
let messageObj = {};
previewMessages.push(messageObj);
messageObj.timeStamp = message.context.latestPost;
messageObj.user = message.context.otherUsername;
messageObj.picture = message.context.itemImageURL;
promises.push(getItemsById([message.context.itemID]).then(itemInfo => {
messageObj.title = itemInfo[Object.keys(itemInfo)[0]].title;
}));
}
// Wait for them all to complete
Promise.all(promises).then(() => {
// use previewMessages
});
如果他们有顺序,请在执行下一步之前等待每一个:
let previewMessages = [];
let promise = Promise.resolve();
// Loop through building up the `then` chain
for (let messageID in messages) {
let message = messages[messageID];
let messageObj = {};
previewMessages.push(messageObj);
// This one will wait for the next
promise = promise.then(() => {
messageObj.timeStamp = message.context.latestPost;
messageObj.user = message.context.otherUsername;
messageObj.picture = message.context.itemImageURL;
return getItemsById([message.context.itemID]).then(itemInfo => {
messageObj.title = itemInfo[Object.keys(itemInfo)[0]].title;
});
});
}
// Wait for the last one to complete
promise.then(() => {
// Use previewMessages
});
但我可能会利用文字来填写我们不必等待的值:
异步:
let previewMessages = [];
let promises = [];
// Build the array of promises
for (let messageID in messages) {
let message = messages[messageID];
let messageObj = {
timeStamp: message.context.latestPost,
user: message.context.otherUsername,
picture: message.context.itemImageURL
};
previewMessages.push(messageObj);
promises.push(getItemsById([message.context.itemID]).then(itemInfo => {
messageObj.title = itemInfo[Object.keys(itemInfo)[0]].title;
}));
}
// Wait for them all to complete
Promise.all(promises).then(() => {
// use previewMessages
});
同步:
let previewMessages = [];
let promise = Promise.resolve();
// Loop through building up the `then` chain
for (let messageID in messages) {
let message = messages[messageID];
let messageObj = {
timeStamp: message.context.latestPost,
user: message.context.otherUsername,
picture: message.context.itemImageURL
};
previewMessages.push(messageObj);
// This one will wait for the next
promise = promise.then(() => {
return getItemsById([message.context.itemID]).then(itemInfo => {
messageObj.title = itemInfo[Object.keys(itemInfo)[0]].title;
});
});
}
// Wait for the last one to complete
promise.then(() => {
// Use previewMessages
});
也许一对简化的,可运行的例子会有所帮助。另外,你已经提到“......问题是func2从func1获取返回对象......”所以让我们将它添加到混合中。
并行:
const messages = {
"one": {name: "Message one"},
"two": {name: "Message two"},
"three": {name: "Message three"},
"four": {name: "Message four"}
};
let previewMessages = [];
let promises = [];
// Build the array of promises
for (let messageID in messages) {
let message = messages[messageID];
let messageObj = {
name: message.name
};
previewMessages.push(messageObj);
promises.push(func1(message).then(func2).then(info => {
messageObj.info = info;
}));
}
// Wait for them all to complete
Promise.all(promises).then(() => {
// use previewMessages
console.log("Done! Result:", previewMessages);
});
function func1(message) {
return new Promise(resolve => {
// Use setTimeout for async
setTimeout(() => {
console.log("func1 resolving on " + message.name);
resolve(message.name + " - func1");
}, Math.random() * 500);
});
}
function func2(info) {
return new Promise(resolve => {
// Use setTimeout for async
setTimeout(() => {
console.log("func2 resolving on " + info);
resolve(info + " - func2");
}, Math.random() * 500);
});
}
.as-console-wrapper {
max-height: 100% !important;
}
序列:
const messages = {
"one": {name: "Message one"},
"two": {name: "Message two"},
"three": {name: "Message three"},
"four": {name: "Message four"}
};
let previewMessages = [];
let promise = Promise.resolve();
// Build the promise chain
for (let messageID in messages) {
let message = messages[messageID];
let messageObj = {
name: message.name
};
previewMessages.push(messageObj);
promise = promise.then(() => func1(message).then(func2).then(info => {
messageObj.info = info;
}));
}
// Wait for the last one to finish
promise.then(() => {
// use previewMessages
console.log("Done! Result:", previewMessages);
});
function func1(message) {
return new Promise(resolve => {
// Use setTimeout for async
setTimeout(() => {
console.log("func1 resolving on " + message.name);
resolve(message.name + " - func1");
}, Math.random() * 500);
});
}
function func2(info) {
return new Promise(resolve => {
// Use setTimeout for async
setTimeout(() => {
console.log("func2 resolving on " + info);
resolve(info + " - func2");
}, Math.random() * 500);
});
}
.as-console-wrapper {
max-height: 100% !important;
}