不是一个“反模式”:--这不是常见的“反模式”,可以通过直接返回嵌套延迟对象来解决.这个摘录是嵌套加载的代码的严重简化,它将在不久的将来返回Deferred,因此不可能直接从原始方法返回尚未存在的Deferreds。
此外,从原始(顶级)方法返回的延迟依赖于在不久的将来创建的多个Deferreds,其中只有“拒绝”被立即回传。
我发现自己最近经常写这样的东西:
My.prototype.init=function() {
var $dfd = $.Deferred();
this.initSomethingElse() // returns Deferred
.done(function() {
$dfd.resolve();
})
.fail(function() {
$dfd.reject();
});
return $dfd;
}
我编写了一个简短的函数来添加.link()方法来简化它,如下所示:
My.prototype.init=function() {
var $dfd = $.Deferred();
this.initSomethingElse() // returns $.Deferred(addLinkMethodFce)
.link($dfd);
return $dfd;
}
但我认为这可能太普遍了,所以其他人可能会想到,我可能错过了jQuery中的一些开箱即用的解决方案。
问题:如果链接对象被解析/拒绝,当前的延迟推断将以同样的方式被解析/拒绝,jQuery能否将现有的延迟对象与其他延迟对象联系起来?
简单地说,就像dfd1Promise = $.when(dfd2)
一样,除了不需要创建新的承诺,而只是简单地将现有的对象“链接”在一起,而不创建新的对象dfd1.link(dfd2)
。
谢谢。
EDIT#1:,当我看到很多问题的答案时,我还没有问--比如“我应该使用延迟推断吗?”我想澄清一下情况。
我有异步加载的代码(My.prototype.init
确实加载异步脚本和数据,从而使其返回给调用方)。
而且,该代码还依赖于异步第三方代码- API不能修改- initSomethingElse()
,该代码也将在不久的将来被解析并返回延迟。
关键是,如果该代码被拒绝,我的代码必须被拒绝。我希望有一些神奇的标准糖语法来重复$theirDfd.reject(function() {$myDfd.reject.call(...);});
,仅此而已。
简单地说,是否有一种标准的方式来执行我的$myDfd.link($theirDfd);
**?** ()
我只是大大简化了情况,用几行文字来表达,所以不要被骗以为我可能不需要延期,或者其他我没有问过的东西……
EDIT#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;
}
EDIT#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;
};
发布于 2016-12-07 10:06:32
TL;博士
问题:如果链接对象被解析/拒绝,当前的延迟推断将以同样的方式被解析/拒绝,jQuery能否将现有的延迟对象与其他延迟对象联系起来?
我知道您在想什么以及为什么;然而,ES2015已经用承诺链解决了这个问题。很好的例子:Promise.all()
(MDN链路)是这种功能的一个很酷的实现(参见:“快速失败”)。
如果需要,可以使用多个延迟的,并使用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/)
阅读本很好的答案关于您的问题(及其相关链接)。答案为什么会对你的情况有帮助,这可能还不清楚,但是给它考虑并编写一些示例代码,你就会更好地理解。
正如其他人提到的那样:
deferred
's。.then()
链接您的承诺(最后是.catch()
)https://stackoverflow.com/questions/41023558
复制相似问题