在解析其他多个延迟对象后解析延迟对象
Resolve deferred object after other multiple deferred objects are resolved
我在$.Deferred
方面的经验非常有限,到目前为止,代码看起来很乱。
本应 return 承诺的函数正在 DOM 更新 HTML 在 ajax 请求后接收到的 HTML。
它的用法是这样的:
this._refreshWorkspace(response.html).then(function(){
// do things after DOM update finished
});
函数代码如下:
_refreshWorkspace: function(htmlBlocks){
var dfd = $.Deferred();
if('editor' in htmlBlocks){
app.destroy(this.editor).then((function(){
this.editor.empty().append(htmlBlocks.editor);
}).bind(this)).then((function(){
app.refresh(this.editor);
}).bind(this));
}
if('listPanels' in htmlBlocks){
app.destroy(this.list).then((function(){
this.list.empty().append(htmlBlocks.listPanels);
}).bind(this)).then((function(){
app.refresh(this.list);
// other unrelated code here
dfd.resolve();
}).bind(this));
}
if('listNav' in htmlBlocks){
// similar code block
}
return dfd;
},
它似乎有效,但前提是提供了 "listPanels" htmlBlock。
我希望 dfd
在所有刷新调用之后被解析一次,或者如果可能的话更好 - 在所有刷新调用都被解析之后。关于如何实现这一点有什么想法吗?
将循环中的所有承诺放入一个数组中,然后使用 $.when
。可悲的是,将 $.when
与数组一起使用是丑陋的:
return $.when.apply($, theArray);
...因为 $.when
旨在接受离散参数而不是数组。
像这样:
_refreshWorkspace: function(htmlBlocks){
var promises = [];
if('editor' in htmlBlocks){
promises.push(
app.destroy(this.editor).then((function(){
this.editor.empty().append(htmlBlocks.editor);
}).bind(this)).then((function(){
app.refresh(this.editor);
}).bind(this))
);
}
if('listPanels' in htmlBlocks){
promises.push(
app.destroy(this.list).then((function(){
this.list.empty().append(htmlBlocks.listPanels);
}).bind(this)).then((function(){
app.refresh(this.list);
}).bind(this))
);
}
if('listNav' in htmlBlocks){
// similar code block
}
return $.when.apply($, promises);
},
这是一个使用随机 Deferred
s 的实例:
function doSomething() {
var promises = [];
var d1, d2, d3;
d1 = new $.Deferred();
promises.push(d1.promise());
setTimeout(function() {
snippet.log("Resolving d1");
d1.resolve(1);
}, Math.floor(Math.random() * 1000));
d2 = new $.Deferred();
promises.push(d2.promise());
setTimeout(function() {
snippet.log("Resolving d2");
d2.resolve(2);
}, Math.floor(Math.random() * 1000));
d3 = new $.Deferred();
promises.push(d3.promise());
setTimeout(function() {
snippet.log("Resolving d3");
d3.resolve(3);
}, Math.floor(Math.random() * 1000));
return $.when.apply($, promises);
}
// Use it
doSomething().then(function() {
snippet.log("All resolved");
});
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
如前所述,问题的简单答案是将各个承诺汇总为 $.when.apply(null, promiseArray)
。
但是,如果问题中的所有代码都代表要应用于所有 html 块的处理,那么您可以更进一步。
jQuery.map()
将对对象的 ownProperties 进行操作,因此可以利用它来迭代 htmlBlocks
,从而产生一个简洁、通用的主例程,其中包含几个支持哈希值。
_refreshWorkspace: function(htmlBlocks) {
var that = this; // avoids the need for .bind(this) in the promise chain and the methodsHash
var propHash = {
'editor': 'editor',
'listPanels': 'list'
};
// All the "other unrelated code" is defined here
var methodsHash = {
'editor': null,
'listPanels': function(key, obj) {
...
},
...
};
//And the main routine is a concise $.map(htmlBlocks, ...) structure.
var promises = $.map(htmlBlocks, function(html, key) {
var obj = that[propHash[key]];
return app.destroy(obj).then(function() {
obj.empty().append(html); //if empty() and append() are jQuery methods then this line is synchronous.
return app.refresh(obj);// if app.destroy() is asynch and theanable, then it seems safe to assume that app.refresh() is also asynch and theanable. Therefore return the result here.
}).then(function() {
if(methodsHash[key]) {
methodsHash[key](key, obj);
}
});
});
//Now aggregate `promises` into a single promise which resolves when all the promises resolve, or rejects when any of the promises rejects.
return $.when.apply(null, promises);
},
现在,为了满足所有其他 html 块的需要,只需向 propHash
添加一行并向 methodsHash
添加一个 null 或函数。只要主程序完整,就不用修改了。
恕我直言,这是组织代码的更好方法。
我在$.Deferred
方面的经验非常有限,到目前为止,代码看起来很乱。
本应 return 承诺的函数正在 DOM 更新 HTML 在 ajax 请求后接收到的 HTML。
它的用法是这样的:
this._refreshWorkspace(response.html).then(function(){
// do things after DOM update finished
});
函数代码如下:
_refreshWorkspace: function(htmlBlocks){
var dfd = $.Deferred();
if('editor' in htmlBlocks){
app.destroy(this.editor).then((function(){
this.editor.empty().append(htmlBlocks.editor);
}).bind(this)).then((function(){
app.refresh(this.editor);
}).bind(this));
}
if('listPanels' in htmlBlocks){
app.destroy(this.list).then((function(){
this.list.empty().append(htmlBlocks.listPanels);
}).bind(this)).then((function(){
app.refresh(this.list);
// other unrelated code here
dfd.resolve();
}).bind(this));
}
if('listNav' in htmlBlocks){
// similar code block
}
return dfd;
},
它似乎有效,但前提是提供了 "listPanels" htmlBlock。
我希望 dfd
在所有刷新调用之后被解析一次,或者如果可能的话更好 - 在所有刷新调用都被解析之后。关于如何实现这一点有什么想法吗?
将循环中的所有承诺放入一个数组中,然后使用 $.when
。可悲的是,将 $.when
与数组一起使用是丑陋的:
return $.when.apply($, theArray);
...因为 $.when
旨在接受离散参数而不是数组。
像这样:
_refreshWorkspace: function(htmlBlocks){
var promises = [];
if('editor' in htmlBlocks){
promises.push(
app.destroy(this.editor).then((function(){
this.editor.empty().append(htmlBlocks.editor);
}).bind(this)).then((function(){
app.refresh(this.editor);
}).bind(this))
);
}
if('listPanels' in htmlBlocks){
promises.push(
app.destroy(this.list).then((function(){
this.list.empty().append(htmlBlocks.listPanels);
}).bind(this)).then((function(){
app.refresh(this.list);
}).bind(this))
);
}
if('listNav' in htmlBlocks){
// similar code block
}
return $.when.apply($, promises);
},
这是一个使用随机 Deferred
s 的实例:
function doSomething() {
var promises = [];
var d1, d2, d3;
d1 = new $.Deferred();
promises.push(d1.promise());
setTimeout(function() {
snippet.log("Resolving d1");
d1.resolve(1);
}, Math.floor(Math.random() * 1000));
d2 = new $.Deferred();
promises.push(d2.promise());
setTimeout(function() {
snippet.log("Resolving d2");
d2.resolve(2);
}, Math.floor(Math.random() * 1000));
d3 = new $.Deferred();
promises.push(d3.promise());
setTimeout(function() {
snippet.log("Resolving d3");
d3.resolve(3);
}, Math.floor(Math.random() * 1000));
return $.when.apply($, promises);
}
// Use it
doSomething().then(function() {
snippet.log("All resolved");
});
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
如前所述,问题的简单答案是将各个承诺汇总为 $.when.apply(null, promiseArray)
。
但是,如果问题中的所有代码都代表要应用于所有 html 块的处理,那么您可以更进一步。
jQuery.map()
将对对象的 ownProperties 进行操作,因此可以利用它来迭代 htmlBlocks
,从而产生一个简洁、通用的主例程,其中包含几个支持哈希值。
_refreshWorkspace: function(htmlBlocks) {
var that = this; // avoids the need for .bind(this) in the promise chain and the methodsHash
var propHash = {
'editor': 'editor',
'listPanels': 'list'
};
// All the "other unrelated code" is defined here
var methodsHash = {
'editor': null,
'listPanels': function(key, obj) {
...
},
...
};
//And the main routine is a concise $.map(htmlBlocks, ...) structure.
var promises = $.map(htmlBlocks, function(html, key) {
var obj = that[propHash[key]];
return app.destroy(obj).then(function() {
obj.empty().append(html); //if empty() and append() are jQuery methods then this line is synchronous.
return app.refresh(obj);// if app.destroy() is asynch and theanable, then it seems safe to assume that app.refresh() is also asynch and theanable. Therefore return the result here.
}).then(function() {
if(methodsHash[key]) {
methodsHash[key](key, obj);
}
});
});
//Now aggregate `promises` into a single promise which resolves when all the promises resolve, or rejects when any of the promises rejects.
return $.when.apply(null, promises);
},
现在,为了满足所有其他 html 块的需要,只需向 propHash
添加一行并向 methodsHash
添加一个 null 或函数。只要主程序完整,就不用修改了。
恕我直言,这是组织代码的更好方法。