【问题标题】:What's a 'deferred' in $q?$q 中的“延迟”是什么?
【发布时间】:2015-09-10 02:55:40
【问题描述】:

我已经阅读了关于 $q 的每篇文章,但不知何故我无法理解它。例如,以我找到的最好的article 为例。我知道:

var myFirstDeferred = $q.defer(); //Actually I don't even get this far

延迟表示异步操作的结果。它公开了一个接口,该接口可用于指示状态和它所表示的操作的结果。它还提供了一种获取相关 Promise 实例的方法。

什么是“延期”?它与承诺有何不同?然后我们得到这个:

async(function(value) {  
    myFirstDeferred.resolve(value);
}, function(errorReason) {
    myFirstDeferred.reject(errorReason);
});

我不知道这是在做什么。我想强调我理解异步。我了解承诺结构。例如,我确切地知道下面的代码在做什么:

$http.get(url)
    .then(function(result){returnresult}
     ,function(error){return error})

但是我们对上面对象中的 deferred 做了什么?为什么还要推迟呢?为什么不只是 then 块?

编辑:我想强调一下,我在这里经历了大量的回复,以及文章。我认为 $q 的重点是强制执行异步调用(有点像 c# 中的“等待”),然后执行一些代码。我真的不明白它是怎么做到的。在此example 中等待多个异步操作时,我确实知道 .all 命令是如何工作的,但不是一个。

编辑:此编辑是对duplicate suggestion 的回应——我不同意这个概念。一方面,这个问题更加集中且范围有限。此外,这里接受的答案比其他 q 中的广网答案更清楚(imo)。

【问题讨论】:

  • 这只不过是任何其他的承诺......这只是 Angular 的一种笨拙的语法。你知道创建 Promise 的标准语法吗? return new Promise(function(resolve, reject) { //etc Angular 让您调用该函数并使用 resolvereject 而不是标准方式返回一个对象:将所有内容包装在新的 Promise 构造函数中,该构造函数接收 resolvereject 作为参数。

标签: angularjs angular-promise deferred


【解决方案1】:

通常您不必显式使用 deferred。如果你发现自己在使用$q.defer,你应该质疑为什么不直接使用 Promise 接口。 See the bluebird documentation for a description of why$http 和许多其他库在内部使用延迟并从它们公开的方法中返回承诺,因此在此之上使用延迟是不必要的。

话虽如此,延迟可能很有用,理解它们很重要。通常,延迟有两种方法:.reject.resolve。老实说,您可以使用一种方法来标记异步操作的结果:

.reject -> the asynchronous operation failed or could not complete
.resolve -> the asynchronous operation completed successfully

当一个 deferred 完成时,它会触发 Promise 回调。

在处理异步但没有内置 promise 接口(如计时器)的操作时,您需要使用 $q.defer 或 deferreds:

var dfd = $q.defer();

$timeout(function () {
    // this is asynchronous

    // it completed successfully
    dfd.resolve("some value");
}, 500);

dfd.promise.then(function (value) {
    assert.equal(value, "some value");
});

而不是使用延迟作为对象接口,Angular allows you to use these destructured as function arguments to $q

重写上面的:

var promise = $q(function (resolve) {
    $timeout(function () {
        resolve("some value");
    }, 500);
});
promise.then(function (value) {
    assert.equal(value, "some value");
});

【讨论】:

  • 所以,我将以 2 岁的方式问这个问题(在哪个级别我会很乐意理解它)。本质上,您创建了一些对象,您所说的某些内容最终会调用“解决”或“拒绝”,即“var someValue = $q.defer(); 然后从代码中的任何地方(理论上,尽管通常来自异步函数)(可能可以看到范围),您调用 someValue.resolve('someArgument')。一旦您进行此调用,您的 someValue.promise 得到解决/拒绝?仍在进行重写部分。
  • @VSO 完全正确。它不一定必须是异步的。它也不完全来自 anywhere ...显然您必须有权访问 someValue 变量
  • 嗯,我想我明白了。至少,我得到的比以前多得多。将不得不考虑重写,但这清楚了很多。真的,非常感谢。
【解决方案2】:

延迟对象只是 Promise 的一个子集,它只给你 .reject 和 .resolve,它可以防止外部世界对它做任何其他事情。如果您无法返回承诺(例如使用基于回调而不是承诺的库时),请延迟并手动拒绝或解决它。

deferred.rejectdeferred.resolve 仅在您返回延迟时才重要。基本上:

somePromise().then( function() {
    var deferred = q.defered();

    someFunctionThatHasCallback( function() {
        deferred.resolve();
    });

    return defererd;
}).then( function() {
    console.log( 'I wait for deferred.resolve' );
});

如果你的函数返回 Promise,你不需要 deferred,因为 Promise 可以通过在 .then 内部返回来链接

somePromise().then( function() {
    return someFunctionThatReturnsPromise();
}).then( function() {
    console.log( 'I wait for promise to resolve' );
});

【讨论】:

  • 谢谢你的回复,我已经通过了。
猜你喜欢
  • 2013-03-18
  • 1970-01-01
  • 2012-09-30
  • 2013-09-11
  • 2013-09-27
  • 2010-09-07
  • 2011-06-19
  • 1970-01-01
  • 2021-09-26
相关资源
最近更新 更多