Jquery.deferred的语法,使同步函数返回promise

时间:2012-05-19 10:43:01

标签: javascript jquery-deferred promise

关于如何使用Jquery.deferred来生成慢速同步函数的快速问题会返回一个promise。 到目前为止我所做的是:

function sayIt(ms) {
    setTimeout( function() { console.log('what I say'); }, ms);
} 

function doIt() {
    return $.Deferred( function() { sayIt(2000); }).promise();
}


doIt().then( function() { console.log('ah'); });

sayIt(2000)总是通过,但'then'之后的链式函数永远不会触发。

如果我这样做:

doIt().then( console.log('ah'));
'啊'马上出现,然后'我说'2000ms之后 - 我想要的当然是相反的 - 两秒后我得到'我说的'然后'啊'之后

任何建议都赞赏!

2 个答案:

答案 0 :(得分:10)

要同步做某事,但仍然使用承诺,请执行:

function slowPromise() {

    var def = $.Deferred();

    // do something slow and synchronous
    ...

    // resolve the deferred with the result of the slow process
    def.resolve(res);

    // and return the deferred
    return def.promise();
}

结果是你仍然得到了一个承诺,但是这个承诺已经解决了,所以随后在其上注册的任何.then()都会立即进行。

这种模式的优点是,如果随后用异步代替同步代码,该函数仍具有相同的外部接口。

答案 1 :(得分:3)

如果要在超时到期后执行函数,则需要在超时到期函数内调用resolve()对象上的Deferred

function sayIt(ms) {
  var d = $.Deferred();
  setTimeout(function() {
      console.log('what I say');
      d.resolve()
    }, ms);
  return d;
}

通过这种方式,您可以将Deferred对象的分辨率限制为超时到期。

为了达到我认为你的意图:

function doIt() {
  return sayIt(2000).promise()
}

.promise()来电是可选的。它仅限制调用者的可用接口:通过返回Promise而不是原始Deferred对象,调用者只能对事件做出反应,但不会触发它们。参考:http://api.jquery.com/deferred.promise/

最后,您的原始电话:

doIt().then( function() { console.log('ah'); });

将输出:

// 2 seconds delay
what I say
ah