$q 中的 'deferred' 是什么?

What's a 'deferred' in $q?

我已经阅读了所有关于 $q 的文章,但不知何故我无法理解它。例如,取我发现的最好的 article。我得到了:

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

A deferred represents the result of an asynchronic operation. It exposes an interface that can be used for signaling the state and the result of the operation it represents. It also provides a way to get the associated promise instance.

什么是 'deferred'?它与承诺有何不同?然后我们得到这个:

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# 中的 "await" ),然后执行一些代码。我真的不明白它是怎么做到的。在这个 example 中等待多个异步操作时,我确实知道 .all 命令是如何工作的,但不是一个。

编辑:此编辑是对 duplicate suggestion 的回应 - 我不同意这个观点。其一,这个问题的重点更集中,范围也更有限。此外,此处接受的答案比其他问题中的广域网答案更清楚(imo)。

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

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

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

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

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

如果您的函数 return 承诺,则不需要延迟,因为承诺可以通过 return 链接到 .then

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

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

话虽如此,deferred 还是很有用的,理解它们很重要。通常,deferreds 有两种方法:.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");
});

而不是使用 deferreds 作为对象接口,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");
});