基本上,我需要在实际创建之前公开Deferred。例如,假设我有一些包装Ajax查询的对象,但在它启动之前需要公开表示该查询的解析的Deferred:
var object = new AjaxRunningThing();
// Get a Deferred wrapping the Ajax operation
var ajaxResult = object.getAjaxResult();
// Later...
// Now the object is going to initiate the Ajax request
object.startAjax();
现在我只是手动链接它们,以便将“真实”延迟的分辨率链接到“外观”中:
// in getAjaxResult()
var publicDeferred = $.Deferred();
// in startAjax()
var privateDeferred = $.ajax(...);
privateDeferred.then(
function() { publicDeferred.resolve.apply(this, arguments); },
function() { publicDeferred.reject.apply(this, arguments); }
);
我不禁想到有更好的方法可以做到这一点。
- 编辑---
考虑更多,我正在寻找的是真正的代理 - 搜索“代理”引导我阅读这篇文章,其中描述了我正在寻找的内容并包含更好的内容(尽管仍然不完全透明)解决方案:Propagating events between JQuery.Deferred objects
答案 0 :(得分:0)
解决级联中的承诺非常简单。我们一直都会看到这一点,通常只有一个承诺就足够了。你在这里需要什么可以被称为"延迟法律模式" (而不是"延迟反模式")。
对我而言,这更多的是关于如何将代码考虑在内而不仅仅是对级联进行编码。
这是一种可行的方法:
function getLatentAjaxPromise(options) {
var dfrd = $.Deferred(),
promise = dfrd.promise(),
jqXHR;
// monkeypatch the promise with a `go()` method.
promise.go = function(opts) {
if(!jqXHR) { // in case .go() is called more than once.
jqXHR = $.ajax($.extend(options, opts)).then(dfrd.resolve, dfrd.reject);
}
return promise;
};
return promise;
};
这将允许:
getLatentAjaxPromise
和/或.go
,getLatentAjaxPromise()
和/或.go()
。请致电如下:
var latentAjaxPromise = getLatentAjaxPromise(...).then(...);
//and later ...
latentAjaxPromise.go(...).then(...);
双胞胎承诺链不应该有任何不良后果,尽管你可能需要保持对你的智慧。从消费者的角度来看,两条链都源于同样的承诺并不是显而易见的。
我很想知道是否有人能在这里发现任何明显的逻辑缺陷。
答案 1 :(得分:0)
只是为了关闭,这是我最终解决的解决方案。它使用了其他答案中的部分,但这是我需要的功能:
// Private deferred that will be resolved when the Ajax is complete
var _done = $.Deferred();
// Expose the deferred as a promise, so it's read-only to other components
var done = _done.promise();
// ... other components add their own callbacks to `done`
// Later, run the ajax, and resolve the deferred based on that
$.ajax(...).then(
_done.resolve, _done.reject, _done.notify);