2

关于如何使用 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'));

“啊”立即出现,然后 2000 毫秒后出现“我说什么”——我想要的当然是相反的——两秒钟后我得到“我说什么”,然后是“啊”。

任何建议表示赞赏!

4

2 回答 2

10

要同步执行某些操作,但仍使用 Promise,请执行以下操作:

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()随后在它上面注册的任何东西都会立即进行。

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

于 2012-05-19T11:04:44.907 回答
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()调用是可选的。它只限制调用者可用的接​​口:通过返回 aPromise而不是原始Deferred对象,调用者只能对事件做出反应,但不能触发它们。参考:http ://api.jquery.com/deferred.promise/ 。

最终,你原来的电话:

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

将输出:

// 2 seconds delay
what I say
ah 
于 2014-07-24T13:56:16.127 回答