When using jQuery promises sequentially, it is possible to chain them using then
repeatedly:
当顺序使用jQuery promises时,可以重复使用它们链接它们:
e.g.
promise = promise.then(someoperation());
which also works inside a loop (very handy).
这也适用于循环(非常方便)。
I have similar scenario where I needed to know when multiple parallel operations were completed, but not go through the coding overhead (e.g. added complexity) of creating an array of promises for the sole purpose of calling $.when.apply
我有类似的情况,我需要知道多个并行操作何时完成,但没有经历编写承诺数组的编码开销(例如增加的复杂性),仅用于调用$ .when.apply
After looking at my options, I came up with this pattern as an alternative:
在查看了我的选项之后,我想出了这种模式作为替代方案:
promise = $.when(promise, anotherpromise);
To test it I came up with this test:
为了测试它我想出了这个测试:
var p = $.Deferred().resolve().promise();
[1,2,3,4,5,6,7,8,9,10].forEach(function(i){
p = $.when(p, delay(i,i * 500));
});
p.then(function(){
log("All done");
});
JSFiddle: http://jsfiddle.net/TrueBlueAussie/0rh8Lhv4/1/
Which appears to work just fine, so I started applying it to other example on *.
哪个似乎工作正常,所以我开始将它应用于*上的其他示例。
The next one I tried with this pattern was to fix the example from Pass in an array of Deferreds to $.when():
我尝试使用此模式的下一个是将示例从Pass中的Deferreds修复为$ .when():
My code:
$("a").click(function () {
var promise = GetSomeDeferredStuff();
promise.then(function () {
$("div").append("<p>All done!</p>");
});
});
JSFiddle: http://jsfiddle.net/TrueBlueAussie/ts1dqwe3/1/
Q. For some reason this one never fires the final event. Can anyone spot the problem?
问:出于某种原因,这个从未触发过最后的赛事。谁能发现问题?
Update
Based on a comment from @Karl-André Gagnon
, it seems the initial promise
can just be undefined and still work. Much simpler:
根据@ Karl-AndréGagnon的评论,似乎最初的承诺可能是未定义的并且仍然有效。更简单:
e.g.
var p;
[1,2,3,4,5,6,7,8,9,10].forEach(function(i){
p = $.when(p, delay(i,i * 500));
});
p.then(function(){
log("All done");
});
2 个解决方案
#1
Okay, it turns out this pattern does indeed work just fine, but you need to ensure the initial promise
you chain to is already resolved:
好的,事实证明这种模式确实很好用,但是你需要确保链接到的初始承诺已经解决:
function GetSomeDeferredStuff() {
var promise = $.Deferred().resolve().promise();
JSFiddle: http://jsfiddle.ne/TrueBlueAussie/ts1dqwe3/2/
In summary this pattern really is a simple alternative to creating an array just for use by $.when.apply
.
总之,这种模式确实是创建一个仅供$ .when.apply使用的数组的简单替代方法。
Also, as pointed out by @Karl-André Gagnon, if you start with an undefined value, it does the same thing. Even better :)
另外,正如@ Karl-AndréGagnon指出的那样,如果你从一个未定义的值开始,它也会做同样的事情。更好:)
function GetSomeDeferredStuff() {
var promise;
#2
Updated
I have similar scenario where I needed to know when multiple parallel operations were completed, but not go through the overhead of creating an array of promises for the sole purpose of calling
我有类似的情况,我需要知道多个并行操作何时完成,但没有完成创建一个promises数组的开销,仅用于调用
loop
not utilized ; only $.when()
; same pattern as utilized when implementing through $.map()
. Additionally , added "random" delay
to jsfiddle ajax request
; promise.then()
should not be called until all parallel function calls at $.when()
completed , next
called , queueName
queue empty .
循环未使用;只有$ .when();与通过$ .map()实现时使用的模式相同。另外,为jsfiddle ajax请求添加了“随机”延迟; promise.then()不应该被调用,直到$ .when()的所有并行函数调用完成,接下来调用,queueName队列为空。
function GetSomeDeferredStuff(elem, name, cycles) {
var el = (elem || {}),
queueName = (name || "q"),
len = (cycles || 5),
request = function () {
return $.ajax({
type: "POST",
url: '/echo/html/',
data: {
html: "<p>Task #" + $.now() + " complete.",
delay: Math.random() * 5
},
success: function (data) {
$("div").append(data);
}
})
}
return $(el).queue(queueName, function (next) {
return $.when(request()
, request()
, request()
, request()
, request())
.then(next)
}).dequeue(queueName).promise(queueName);
}
$(function () {
$("a").click(function () {
var promise = GetSomeDeferredStuff();
promise.then(function () {
$("div").append("<p>All done!</p>");
});
});
});
jsfiddle http://jsfiddle.net/ts1dqwe3/10/
When using jQuery promises sequentially, it is possible to chain them using then repeatedly ... which also works inside a loop (very handy).
当顺序使用jQuery promises时,可以使用重复链接它们......这也可以在循环内部工作(非常方便)。
Try utilizing .queue()
.promise(queueName)
尝试使用.queue().promise(queueName)
function GetSomeDeferredStuff(elem, name, cycles) {
// if no `elem`:`this` object passed , utilize empty object `{}`
var el = (elem || {})
// if no `name` passsed, utilize `String` `"q"`
, queueName = (name || "q")
// if no `cycles` how many functions passed to `.queue(queueName)`,
// pass `5` functions to `.queue(queueName)`
, len = (cycles || 5);
return $(el).queue(queueName
, $.map(Array(len), function (_, index) {
return function (next) {
return $.ajax({
type: "POST",
url: '/echo/html/',
data: {
html: "<p>Task #" + (1 + index) + " complete.",
delay: (index + 1) / 2
},
success: function (data) {
return $("div").append(data);
}
// call "next" function in `queue`
}).then(next)
}
// `.dequeue(queueName)` , return `queueName` jQuery promise object,
// when all functions in `queue(queueName)` called ;
// `.queue(queueName)` empty
})).dequeue(queueName).promise(queueName);
}
$(function () {
$("a").click(function () {
var promise = GetSomeDeferredStuff();
promise.then(function () {
// `this`:`elem` , or `{}`
$("div").append("<p>All done!</p>");
});
});
});
jsfiddle http://jsfiddle.net/ts1dqwe3/6/
#1
Okay, it turns out this pattern does indeed work just fine, but you need to ensure the initial promise
you chain to is already resolved:
好的,事实证明这种模式确实很好用,但是你需要确保链接到的初始承诺已经解决:
function GetSomeDeferredStuff() {
var promise = $.Deferred().resolve().promise();
JSFiddle: http://jsfiddle.ne/TrueBlueAussie/ts1dqwe3/2/
In summary this pattern really is a simple alternative to creating an array just for use by $.when.apply
.
总之,这种模式确实是创建一个仅供$ .when.apply使用的数组的简单替代方法。
Also, as pointed out by @Karl-André Gagnon, if you start with an undefined value, it does the same thing. Even better :)
另外,正如@ Karl-AndréGagnon指出的那样,如果你从一个未定义的值开始,它也会做同样的事情。更好:)
function GetSomeDeferredStuff() {
var promise;
#2
Updated
I have similar scenario where I needed to know when multiple parallel operations were completed, but not go through the overhead of creating an array of promises for the sole purpose of calling
我有类似的情况,我需要知道多个并行操作何时完成,但没有完成创建一个promises数组的开销,仅用于调用
loop
not utilized ; only $.when()
; same pattern as utilized when implementing through $.map()
. Additionally , added "random" delay
to jsfiddle ajax request
; promise.then()
should not be called until all parallel function calls at $.when()
completed , next
called , queueName
queue empty .
循环未使用;只有$ .when();与通过$ .map()实现时使用的模式相同。另外,为jsfiddle ajax请求添加了“随机”延迟; promise.then()不应该被调用,直到$ .when()的所有并行函数调用完成,接下来调用,queueName队列为空。
function GetSomeDeferredStuff(elem, name, cycles) {
var el = (elem || {}),
queueName = (name || "q"),
len = (cycles || 5),
request = function () {
return $.ajax({
type: "POST",
url: '/echo/html/',
data: {
html: "<p>Task #" + $.now() + " complete.",
delay: Math.random() * 5
},
success: function (data) {
$("div").append(data);
}
})
}
return $(el).queue(queueName, function (next) {
return $.when(request()
, request()
, request()
, request()
, request())
.then(next)
}).dequeue(queueName).promise(queueName);
}
$(function () {
$("a").click(function () {
var promise = GetSomeDeferredStuff();
promise.then(function () {
$("div").append("<p>All done!</p>");
});
});
});
jsfiddle http://jsfiddle.net/ts1dqwe3/10/
When using jQuery promises sequentially, it is possible to chain them using then repeatedly ... which also works inside a loop (very handy).
当顺序使用jQuery promises时,可以使用重复链接它们......这也可以在循环内部工作(非常方便)。
Try utilizing .queue()
.promise(queueName)
尝试使用.queue().promise(queueName)
function GetSomeDeferredStuff(elem, name, cycles) {
// if no `elem`:`this` object passed , utilize empty object `{}`
var el = (elem || {})
// if no `name` passsed, utilize `String` `"q"`
, queueName = (name || "q")
// if no `cycles` how many functions passed to `.queue(queueName)`,
// pass `5` functions to `.queue(queueName)`
, len = (cycles || 5);
return $(el).queue(queueName
, $.map(Array(len), function (_, index) {
return function (next) {
return $.ajax({
type: "POST",
url: '/echo/html/',
data: {
html: "<p>Task #" + (1 + index) + " complete.",
delay: (index + 1) / 2
},
success: function (data) {
return $("div").append(data);
}
// call "next" function in `queue`
}).then(next)
}
// `.dequeue(queueName)` , return `queueName` jQuery promise object,
// when all functions in `queue(queueName)` called ;
// `.queue(queueName)` empty
})).dequeue(queueName).promise(queueName);
}
$(function () {
$("a").click(function () {
var promise = GetSomeDeferredStuff();
promise.then(function () {
// `this`:`elem` , or `{}`
$("div").append("<p>All done!</p>");
});
});
});
jsfiddle http://jsfiddle.net/ts1dqwe3/6/