简短的问题是:对于多个并发的 Promise,如何在所有 Promise 成功或失败后让某些事情在最后发生? (而不是在 1 个 promise 失败后立即做某事)。
我认为它适用于 jQuery Deferreds 或 AngularJS Deferreds,并且要求是,假设屏幕上有 16 个方形面板,布局为 4 x 4 网格。
用户可以单击“获取”或“刷新”来刷新每个方形面板,并且将为该特定面板获取数据。
所以这是一个简单的 Promise 情况:16 个 Promise。
但是,如果需要一个全局“旋转轮”(例如在视口(viewport)的右上角)怎么办?只要一个方形面板正在等待数据,或者 2 个、3 个或更多面板正在等待数据,它就会显示出来。当所有数据获取成功或失败时,旋转的轮子应该消失。但关键是,当单个数据获取失败时,不应该认为整个操作失败并立即隐藏旋转轮。
有没有办法使用 $.when()
或 $.pipe()
来完成这项工作? $.when()
看似“与”的关系,但任何一次失败的抓取都会使操作被认为完全失败并立即隐藏旋转轮。我们可以使用 $.when()
作为新的 Promise,从而以某种方式使用它来报告“进度”吗? (但如何?)。 (实际上,如果when()
可以返回一个可以观察进度的promise,数据为{total:8, success:3,fail:1,pending:4}
,那么它可能会满足我们所需要的需求。我们只需要根据pending
是否为0
来显示或隐藏旋转轮,这非常简单。
一个简单的可行方法就是为“事件”方形面板的数量设置一个计数器。当每个面板开始获取数据时,递增计数器,并且在获取成功或失败时,然后递减计数器,但如果它是 float 的全局变量,则可能不那么干净。
另一种方法可能是构建一个overallPanel对象,它“有”(意思是组合)16个squarePanel对象,并且每个squarePanel本身需要是一个可观察对象,以便overallPanel将观察每个对象,并递增或递增递减一个计数器,当 counter > 0 时显示旋转轮,当 counter == 0 时隐藏。(因此,当每个 squarePanel 获取数据成功或失败时,它会依次解析或拒绝自身,以通知观察者,这是总体面板)
或者有没有办法使用内置的 Promise 或 Deferred 函数?
最佳答案
嗯,就像你说的,你有 $.when
和 $q.all
,它们实际上都是来自 native 的 Promise.all
(和 bluebird ) promise 。
您缺少的是一个 reflect
原语,它将拒绝转换为实现并以某种方式指示所述失败:
var res = Promise.all(promises.map(x => x.then(v => ({v, good: true}),
e => ({e, bad: true})));
这会让你这样做:
res.then(results => {
let good = results.filter(x => x.good);
let bad = results.filter(x => x.bad);
});
无论结果是好是坏。无需实现自己的逻辑来计算 promise 。
关于javascript - 如何在 "AND"关系中组合 deferreds/promise,但不将单个拒绝计为整体拒绝?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34692922/