以角度

时间:2015-12-16 21:25:43

标签: javascript angularjs angular-promise

我对角度很陌生,而且我被推进了一个相当大的项目。我的情况已经简化为以下代码:

var beforeClose = function() {
    var closeDeferred = $q.defer(),
    a = $q.defer(),
    b = $q.defer(),
    c = $q.defer(),
    promiseArray = [a.promise, b.promise, c.promise];

    /* logic that resolves or rejects a, b, and c */

    $q.all(promiseArray).then(
        function() {
            closeDeferred.resolve();
        },
        function() {
            closeDeferred.reject();
        }
    );
    return closeDeferred.promise;
}

var modalClose = function() {
    beforeClose().then(
        function() {
            //close the modal
        },
        function() {
            //warn and don't close modal
        }
    )
}

使用Chrome的DevTools,似乎代码在完全解决或拒绝 closeDeferred之前返回promiseArray承诺。所以我想我的问题就像,

什么时候承诺退回?可以在解决或拒绝之前退回吗?如果没有,我怎么能阻止它返回?

将return语句放入函数(例如,在promiseArray resolve和reject函数中)使该函数返回promise,但不一定将该promise发送给modalClose(这解雇了第一个承诺)。

或许我理解我的代码会发生什么。当我将返回closeDeferred放入另一个函数时,我发现错误,指出.then()无法在未定义时调用(指向beforeClose().then() })。

修改:在查看安德鲁的回答之后,我不得不更新代码,并且更具体地说明了发生了什么。 问题不一定是在我想要之前返回承诺,而是它正在为该承诺执行解析函数 - 它会关闭模态,即使promiseArray()没有& #39; t完成它的事情。

编辑2:所以看来,在简化代码结构时,我实际上删除了我的真正问题。在承诺的各种设置中,事实证明我在返回语句之前从未实际将closeDeferred定义为延迟或承诺。因此,当循环机制完成了它应该做的事情时,它也会返回closeDeferred.promise,未定义,我猜?所以modalClose函数在任何promises被解析/拒绝之前运行。然后在下一个循环中,最终定义了closeDeferred,并且承诺正确地起作用。

尽管如此,我真的很感激所给予的帮助。 @ andrew-tomlinson和@georgeawg都让我对承诺有了更好的理解。它没有回答这个问题(因为我错误地定义了这个问题),但它肯定非常有用。谢谢!

3 个答案:

答案 0 :(得分:5)

乍一看,您似乎正在使用Defer对象加载promiseArray。根据文档(在这里找到:https://docs.angularjs.org/api/ng/service/ $ q),似乎all()方法需要一个Promise对象数组。

要从Defer对象获取承诺,您可以将其作为属性访问:

var myDeferedObj = $q.defer();
var myPromiseObj = myDeferedObj.promise;

然后你将在promiseArray中使用promise对象。在您的示例中实现的这个想法会将其改为:

a = $q.defer().promise,
b = $q.defer().promise,
c = $q.defer().promise,
promiseArray = [a,b,c];

注意,我没有亲自测试过,但是如果你仍然被卡住,你可以尝试一下。祝你好运!

编辑:在更彻底地阅读了一些问题之后,我觉得我需要改变我的回答以解决一些具体问题。如果您已经知道这一点,我很抱歉,我错过了问题的重点。

"承诺何时返回?"

执行return方法时,从函数返回Promise对象。返回promise对象在概念上与解析或拒绝promise无关。返回Promise对象通常是为了在应用程序中传递Promise的引用。在您的示例中,您将Promise对象从beforeClose()函数传递给modalClose()函数。在承诺被解决或拒绝之前,.then(function(){},function(){})内的Promise对象(使用modalClose())上提供的回调函数将不会执行。

"可以在解决或拒绝之前退回吗?"

是的,Promise对象closeDeferred.promise将立即从beforeClose()返回,但是根据我对示例代码的理解,在promiseArray中的promise被解决或拒绝之前,不应该解析或拒绝它统称。也就是说,return closeDeferred.promise;不是阻塞语句,并且将像函数末尾的任何正常return语句一样执行。

有一个非常简单的(非常简单的)Promise概念的例证here被解释为卡通片。

答案 1 :(得分:2)

返回 #!/bin/sh # unix time in s that we should wake at waketime=$(date +%s -d '08:00') # make sure the time we got is in the future if [ $(date +%s) -gt $waketime ]; then # if not add a day 60s * 60s * 24h waketime=$(($waketime + 86400)) fi # time in S from now till then dif=$(($waketime - $(date +%s))) # tell the user echo echo "Current Time : $(date +%s)" echo "Wake Time : $waketime" echo "Seconds From Now : $dif" echo echo "Crtl-C to Cancel in 5s" echo sleep 5 # sleep with rtcwake /usr/sbin/rtcwake -m off -l -s $dif echo "Shutdown." 承诺。

$q.all

请注意var beforeClose = function() { //var closeDeferred = $q.defer(), var a = $q.defer(), var b = $q.defer(), var c = $q.defer(), var promiseArray = [a.promise, b.promise, c.promise]; /* logic that resolves or rejects a, b, and c */ var pAll = $q.all(promiseArray).then( function(resultsList) { resultsA = resultsList[0]; resultsB = resultsList[1]; resultsC = resultsList[2]; return something; }, function(error) { throw error; } ); return pAll; } 不具弹性。如果任何promises抛出错误,它将解决(被拒绝)第一个错误。

$q.all功能会立即返回承诺。承诺将在将来中的某些时间解决(包含数据或错误)。 $q.all服务延迟了$q方法中函数的执行,直到promise用数据解析;在.then方法中有错误。

.catch

答案 2 :(得分:0)

我可能会误读这一点,但您似乎应该发送$q.all个承诺对象并使用承诺的内置.catch功能:

var beforeClose = function() {
    var closeDeferred = $q.defer(),
    a = $q.defer().promise, // send promise objects to promiseArray
    b = $q.defer().promise, // send promise objects to promiseArray
    c = $q.defer().promise, // send promise objects to promiseArray
    promiseArray = [a,b,c];

    /* logic that resolves or rejects a, b, and c */

    $q.all(promiseArray)
    .then(closeDeferred.resolve();)
    .catch(closeDeferred.reject();)

    return closeDeferred.promise;
}

var modalClose = function() {
    beforeClose()
    .then( //close the modal )
    .catch( //warn and don't close modal );
}