问题
setTimeout ->
console.log 'foo'
setTimeout ->
console.log 'bar'
setTimeout ->
console.log 'baz'
, 1000
, 1000
, 1000
Is it possible to achieve the same result with jQuery.Deferred? Something like the following, perhaps:
someFunction()
.then(-> console.log 'foo')
.then(delay 1000)
.then(-> console.log 'bar')
.then(delay 1000)
.then(-> console.log 'baz')
Perhaps I'm wrong in thinking promises make it easy to write: Do A, then once that finishes, do B, then once that finishes, do C.
回答1:
You can chain the .then()
calls by returning a new Deferred
object. Specifically for delaying, you could use something like:
function someFunction() {
var ret = new $.Deferred();
// setTimeout just to simulate `someFunction` taking 1000ms to complete its deferred
setTimeout(function () {
ret.resolve();
}, 1000);
return ret;
}
function logger(str) {
return function () {
console.log("Logger:", str);
};
}
function delay(time) {
return function () {
console.log("Delaying");
var ret = new $.Deferred();
setTimeout(function () {
ret.resolve();
}, time);
return ret;
};
}
someFunction()
.then(logger("foo"))
.then(delay(3000))
.then(logger("bar"))
.then(delay(3000))
.then(logger("baz"));
DEMO: http://jsfiddle.net/yGcfu/
回答2:
Yes it is:
delay = (ms) -> ->
d = $.Deferred()
setTimeout d.resolve, ms
d.promise()
(demo at jsfiddle.net)
Or, more common for a delay
method, you omit the closure (one ->
) and use
….then(-> delay 1000) …
来源:https://stackoverflow.com/questions/17983331/using-jquery-deferred-to-avoid-nested-settimeout-callbacks