使用 jQuery.Deferred 避免嵌套的 setTimeout 回调

Posted

技术标签:

【中文标题】使用 jQuery.Deferred 避免嵌套的 setTimeout 回调【英文标题】:Using jQuery.Deferred to avoid nested setTimeout callbacks 【发布时间】:2013-08-01 17:49:56 【问题描述】:
setTimeout ->
  console.log 'foo'
  setTimeout ->
    console.log 'bar'
    setTimeout ->
      console.log 'baz'
    , 1000
  , 1000
, 1000

是否可以使用 jQuery.Deferred 实现相同的结果?可能类似于以下内容:

someFunction()
.then(-> console.log 'foo')
.then(delay 1000)
.then(-> console.log 'bar')
.then(delay 1000)
.then(-> console.log 'baz')

也许我错误地认为 promise 让编写变得容易:做 A,完成后做 B,完成后做 C

【问题讨论】:

类似的东西?:jsfiddle.net/gxFkn 确实!您想添加它作为答案吗? 【参考方案1】:

您可以通过返回 new Deferred 对象来链接 .then() 调用。特别是为了延迟,你可以使用类似的东西:

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"));

演示: http://jsfiddle.net/yGcfu/

【讨论】:

【参考方案2】:

是的:

delay = (ms) -> ->
    d = $.Deferred()
    setTimeout d.resolve, ms
    d.promise()

(demo at jsfiddle.net)

或者,对于delay 方法更常见的是,您省略闭包(一个->)并使用

….then(-> delay 1000) …

【讨论】:

以上是关于使用 jQuery.Deferred 避免嵌套的 setTimeout 回调的主要内容,如果未能解决你的问题,请参考以下文章

拥抱基于jquery.deferred的ajax,和层层嵌套回调的ajax说拜拜

jQuery.Deferred对象

Deferred

jQuery: Deferred

jquery Deferred

jQuery异步框架探究2:jQuery.Deferred方法