Using jQuery.Deferred to avoid nested setTimeout callbacks

南笙酒味 提交于 2019-12-30 22:59:48

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!