我目前正在尝试使用javascript中的异步调用生成一对数组但是我似乎无法以正确的顺序获取它。
generateDataPoints: function (iterable, source, arg) {
let pairs = []
let prevTime = 0
for (let index in iterable) {
let event = iterable[index]
getTime(event.valueOf()).then(function (time) {
query(source[arg], event.valueOf()).then(function(val) {
if (time !== prevTime) {
prevTime = time
pairs.push([time, val])
console.log(pairs) // This works as expected but only happens after the program returns
} else {
Promise.resolve()
}
})
})
}
return Promise.resolve(pairs)
}
问题在于" pairs.push .."命令发生在我返回后。我无法弄清楚到底出了什么问题,以及如何同步这个过程。任何帮助表示赞赏。
答案 0 :(得分:0)
您正在使用异步代码混合同步代码(如for循环)。尝试这样的事情:
function generateDataPoints(iterable, source, arg) {
let prevTime = 0
[...iterable].reduce((promiseChain, event) => {
let pairs;
return promiseChain
.then(p => {
pairs = p;
return Promise.all([
getTime(event.valueOf()),
query(source[arg], event.valueOf())
])
})
.then(([time, val]) => {
if (time !== prevTime) {
prevTime = time
return pairs.concat([[time, val]]);
} else {
return pairs;
}
});
})
}, Promise.resolve([]));
}
这会将iterable
缩减为顺序的Promise链,最终将包含所有对。
如果您的环境允许,您还可以将您的功能转换为 async 功能,只需进行少量更改:
generateDataPoints: async function (iterable, source, arg) {
let pairs = []
let prevTime = 0
for (let index in iterable) {
let event = iterable[index]
const [time, val] = await Promise.all([
getTime(event.valueOf()),
query(source[arg], event.valueOf())
]);
if (time !== prevTime) {
prevTime = time
pairs.push([time, val])
}
}
return pairs;
}
修改强>:
仔细看,看起来你需要对这些Promise进行序列化。您也许可以并行运行它们:
function generateDataPoints(iterable, source, arg) {
Promise.all(
[...iterable].map(event => Promise.all([
getTime(event.valueOf()),
query(source[arg], event.valueOf())
])
).then(pairs => {
let prevTime = 0
return pairs.filter(([time, val]) => {
if (time !== prevTime) {
prevTime = time;
return true;
} else {
return false;
}
});
});
}