NOT AN" ANTIPATERN" :这不常见"反模式"简单地通过直接返回嵌套的Deferred对象就可以解决这个摘录...这个摘录是嵌套的延迟加载代码的大量简化,它将在不久的将来返回Deferred,因此不可能直接从原始方法返回尚未存在的Deferred。
除此之外,从原始(顶级)方法返回的延迟取决于在不久的将来创建的多个延迟,其中只有"拒绝"马上回来......
我发现自己最近经常写这样的事情:
My.prototype.init=function() {
var $dfd = $.Deferred();
this.initSomethingElse() // returns Deferred
.done(function() {
$dfd.resolve();
})
.fail(function() {
$dfd.reject();
});
return $dfd;
}
我写了一个简短的函数,在Deferred上添加.link()方法,简化如下:
My.prototype.init=function() {
var $dfd = $.Deferred();
this.initSomethingElse() // returns $.Deferred(addLinkMethodFce)
.link($dfd);
return $dfd;
}
但我认为它可能太普遍了,所以其他人可能会想到它而我可能错过了jQuery中的一些开箱即用的解决方案。
问题:jQuery是否可以链接现有Deferred对象与其他Deferred对象的方式,如果链接对象被解析/拒绝当前Deferred将以相同方式解析/拒绝?
像dfd1Promise = $.when(dfd2)
之类的东西,除了不需要创建新的Promise而只需简单地#34;链接"将现有对象放在一起而不创建新对象dfd1.link(dfd2)
。
感谢。
编辑#1:我看到许多问题的答案我还没有问过 - 比如"我应该使用延期吗?"我想澄清一下情况。
我正在使用异步加载的代码(My.prototype.init
会加载异步脚本和数据,使其返回延迟到调用者)。
该代码还依赖于异步第三方代码 - 我无法修改的API - initSomethingElse()
也将在不久的将来解决,并返回Deferred。
重点是,如果该代码被拒绝,我的代码必须被拒绝。而且我希望有一些神奇的标准糖语法可以重复$theirDfd.reject(function() {$myDfd.reject.call(...);});
。
只是有一种标准方式来执行$myDfd.link($theirDfd);
我只是简单地简化了这种情况,以便在几行上表达出来,所以不要误以为我可能不需要延期或其他任何我没有问过的......
编辑#2:为了进一步澄清.link()的作用,这里是我目前使用的帮助代码:
/**
* Adds some syntax sugar methods to Deferred object.
*
* Deferred.link(dfd, ...) - if this object resolves/rejects/progresses it will resolve/reject/progress linked object as well
* Deferred.linkResolve(dfd, ...) - if this object resolves it will resolve linked object as well
* Deferred.linkReject(dfd, ...) - if this object rejects it will reject linked object as well
* Deferred.linkProgress(dfd, ...) - if this object progresss it will progress linked object as well
*
* Methods can be appended to Deferred object by two ways:
*
* $dfd = edfd($.Deferred());
* $dfd = $.Deferred(edfd);
*
* @access public
* @return {Deferred}
*/
function edfd($dfd) {
/**
* Helper used by this.link(), this.linkReject(), this.linkProgress(), this.linkResolve()
*
* @access private
* @param {Boolean} accept link this Deferred's accept call to target's accept
* @param {Boolean} reject link this Deferred's reject call to target's reject
* @param {Boolean} progress link this Deferred's progress call to target's progress
* @param {Object} targets array of Deferreds or array of arrays of Deferreds
* @return {Deferred} this (called in $dfd context)
*/
function linker(accept, reject, progress, targets) {
targets = dna.core.getOpts(targets, [['dfdList', 'object'], 'recursive']);
for (var i = 0; i < targets.dfdList.length; i++) {
var $link = targets.dfdList[i];
$dfd.then(
accept && function() {$link.resolve.apply($link, arguments);},
reject && function() {$link.reject.apply($link, arguments);},
progress && function() {$link.progress.apply($link, arguments);}
);
}
return this;
}
/**
* If link this Deferred's rejection/resolution/progress to all linked Deferreds.
*
* @access public
* @param {...Deferred} dfd jQuery Deferred objects or arrays of Deferred objects.
* @return {Deferred} this object
*/
$dfd.link = function() {
return linker(true, true, true, arguments);
};
/**
* If this Deferred is resolved then resolve also linked Deferreds.
*
* @access public
* @param {...Deferred} dfd jQuery Deferred objects or arrays of Deferred objects.
* @return {Deferred} this object
*/
$dfd.linkResolve = function() {
return linker(true, false, false, arguments);
};
/**
* If this Deferred gets rejected then reject also linked Deferreds.
*
* @access public
* @param {...Deferred} dfd jQuery Deferred objects or arrays of Deferred objects.
* @return {Deferred} this object
*/
$dfd.linkReject = function() {
return linker(false, true, false, arguments);
};
/**
* If this Deferred progresses then progress also linked Deferreds.
*
* @access public
* @param {...Deferred} dfd jQuery Deferred objects or arrays of Deferred objects.
* @return {Deferred} this object
*/
$dfd.linkProgress = function() {
return linker(false, false, true, arguments);
};
return $dfd;
}
编辑#3:仅适合那些渴望特殊用途的人。延迟对象的初始化与此this.$dfd = $.Deferred(edfd);
一样初始化(请参阅我上面针对此问题的解决方案 - function edfd(...)
/**
* Public interface as required for payment processors.
*
* @access public
* @param {Object} payData
* @return {Deferred} resolved/rejected based on payment result.
*/
Braintree.prototype.process = function(payData) {
this.cleanUp();
this.payData = payData;
this.createLayer();
this.initBraintree(payData.clientToken)
.linkReject(this.$dfd);
return this.$dfd;
};
答案 0 :(得分:-1)
<强> TL; DR 强>
问题:jQuery是否可以链接现有Deferred对象与其他Deferred对象的方式,如果链接对象被解析/拒绝当前Deferred将以相同方式解析/拒绝?
我看到你在想什么以及为什么;然而,ES2015已经通过Promise链接为您解决了这个问题。很好的例子:Promise.all()
(MDN link)是这类功能的一个很酷的实现(参见:&#34;快速失败&#34;)。
如果您需要,请使用多个延期&#34;链接&#34;他们一起使用jQuery.when()
var d1 = $.Deferred();
var d2 = $.Deferred();
$.when( d1, d2 ).done(function ( v1, v2 ) {
console.log( v1 ); // "Fish"
console.log( v2 ); // "Pizza"
});
d1.resolve( "Fish" );
d2.resolve( "Pizza" );
(代码来源:https://api.jquery.com/jquery.when/)
在SO上阅读此good answer关于您的问题(及其相关链接)。可能不会立即明白为什么答案有助于你的案例,但要考虑并编写一些示例代码,你就能更好地理解。
正如其他人所暗示的那样:
deferred
,如果可能的话.then()
(最后.catch()