假设newsService.getNews()
返回一个应该解析为某个服务返回的随机新闻条目的promise,而translateService.translate()
返回一个应该解析为传递文本转换的promise。
var newsPromises = [];
var translatePromises = [];
for (var i = 0; i < 5; i++) {
var p1 = this.newsService.getNews();
newsPromises.push(p1);
p1.then(function (data) {
var p2 = this.translateService.translate(data);
translatePromises.push(p2);
p2.then(function (translatedData) {
addNews(`${data} (${translatedData})`);
}, function (fail) {
console.log(fail.message);
});
}, function (fail) {
console.log(fail.message);
});
}
现在页面最初显示了一个加载微调器,当所有promise(包括嵌套转换promise)完成(成功或失败)时,我想隐藏它:
Promise.all(newsPromises)
.then(function (results) {
Promise.all(translatePromises).then(function (results) {
removeLoading();
},
function (err) {
removeLoading();
}
);
}, function (err) {
Promise.all(translatePromises).then(function (results) {
removeLoading();
},
function (err) {
removeLoading();
}
);
});
这段代码a)不能正常工作,因为加载微调器有时会在promises解决之前消失,而b)非常复杂。
这是如何正确完成的? (与香草JS / ES6)
答案 0 :(得分:1)
请记住,promises链是管道,当结果通过处理程序时,每个处理程序都可以转换链的结果。见评论:
// We only need one array of promises
const promises = [];
// Build the array
for (let i = 0; i < 5; i++) {
// Add this promise to the array
promises.push(
// Get the news...
this.newsService.getNews().then(
// ...and translate it...
data => this.translateService.translate(data)
.then(translatedData => {
// ...and show it as soon as it's available
addNews(`${data} (${translatedData})`);
// Note that here we're converting the resolution value to
// `undefined`, but nothing uses it so...
// If you want something to be able to use it,
// return `translatedData` (or `data` or...)
})
)
.catch(fail => {
console.log(fail.message);
// WARNING: Here you're converting rejection to resolution with `undefined`
})
);
}
// Wait until all that is done before removing the loading indicator
Promise.all(promises).then(removeLoading);
请注意,我们在catch
承诺上不需要Promise.all
的唯一原因是您忽略了(除了记录)发生的错误,因此我们知道承诺永远不会拒绝
另请注意,上述假设removeLoading
不会关注它收到的参数,并且它不会返回可能拒绝的承诺。如果它关心参数并且在没有参数的情况下调用它很重要,请将Promise.all
位更改为:
Promise.all(promises).then(() => removeLoading());
如果它返回可能拒绝的承诺,您还需要一个catch
处理程序。
答案 1 :(得分:0)
在这种情况下我创建了全局计数器loadersCount = 0
每次致电this.newsService.getNews()
来电函数loaderStart()
每次致电addNews()
或console.log(fail.message)
致电loaderStop()
function loaderStart () {
if (loadersCount === 0) {
addLoading();
}
loadersCount++;
}
function loaderStop () {
if (loadersCount === 1) {
removeLoading();
}
loadersCount--;
}