AFAIK Deferreds只能解决一次,但我有一个场景,我在表格中存储了很多Deferreds。这些延期可能会导致这种情况发生。值将需要更新但其他模块将要存储对原始延迟的本地引用,因此我不能用新对象覆盖整个延迟。
我是否有某种方法可以覆盖延期价值,或者如果(我怀疑)它是不可取的(甚至是不可能的)是否有任何经过试验和测试的方法来解决这个问题?这里有一些框架代码来说明问题
// articles module
var articles = {},
// anId = 'uuid';
articles[anId] = $.get('/articles/' + anId);
//another module
var localCopyOfArticle,
getArticle = function (anId) {
localCopyOfArticle = articles[anId]
}
getArticle('uuid');
// back to articles
articles[anId] = $.get('/articles/refresh/' + anId);
//another module again
console.log(localCopyOfArticle) // oh no - it's out of date
答案 0 :(得分:2)
AFAIK Deferreds只能解决一次
正确。从待处理状态转换为已履行或已拒绝状态(也已解决)的承诺不再能够改变状态。承诺规范明确地说明了这一点:
当履行/拒绝时,承诺不得过渡到任何其他州。
所以,你有它,没有 - 承诺在解决后不会改变状态。就像返回值的函数一样,回想起来不会突然抛出异常。每当你不确定时 - 考虑同步代码类比
var x = foo(); // returns correctly
// .. more code
你不希望{<1}}在返回之后抛出,或者在投掷之后返回,就像你不希望承诺在解决后拒绝或在拒绝后解决。
我是否有某种方法可以覆盖延迟的价值,或者如果(我怀疑)它是不可取的(甚至不可能)是否有任何经过试验和测试的方法来解决这个问题?这是一些用于说明问题的框架代码
不,承诺是对单一计算的滥用。解决它两次是没有意义的。对你的目标来说,这似乎是错误的抽象。
Promise是一个很好的流量控制机制,但它们并不是要解决asnychronosu代码必须处理的每个问题。它们不是一个事件发射器。
然而,这个问题很容易通过承诺来解决:
foo
这段代码有很多“残酷”来说明这一点。重要的是要意识到操作每次都是一个新的操作。每次获取数据都是一项新操作,而不是同一项操作。就像在同步代码中一样。将值存储在映射中而不是promises中,并且fetch操作应该基于promise。
答案 1 :(得分:0)
而不是将deferred存储在articles模块中,您可以存储jquery Callbacks对象,并在ajax调用完成时触发它。这将允许您拥有多个订阅者,并允许您多次通知每个订阅者:
// articles module
var articles = {},
// anId = 'uuid';
// create jquery callbacks object.
articles[anId] = $.Callbacks();
// load the article and fire all callbacks that have been added to articles[anId]
$.get('/articles/' + anId)
.then(function (data) { articles[anId].fire(data); });
// add a callback to articles[anId] whose purpose is to keep localCopyOfArticle up to date.
var localCopyOfArticle = null;
articles[anId].add(function(data) {
localCopyOfArticle = data;
});
// back to articles
articles[anId] = $.get('/articles/refresh/' + anId)
.then(function (data) { articles[anId].fire(data); });