javascript - 如何使用 $q.all 跨多个异步函数处理 $http.get 的结果

标签 javascript promise q angular-promise

我有一组从 $http.get 返回的对象,我需要对其执行三个不同的自主后处理。我相信我可以使用 $q.all 并行执行后处理。

我看到大量使用遵循此模式的 $timeout/setTimeout 的示例:

function doSomethingAsync() {
    var deferred = $q.defer();

    setTimeout(function() {
        deferred.resolve('hello world');
    }, 500);

    return deferred.promise;
}

doSomethingAsync().then(function(val) {
    console.log('Promise Resolved!', val);
});

我是 javascript 的新手,但这并不是我问题的核心。 $timeout 和 setTimeout 函数已经是异步的,因此 doSomethingAsync 只是通过返回 promise 而落空了......没有实际工作内联完成。

在下面的例子中,我不明白函数是如何在执行后立即返回 promise 的。 “return deferred.promise”会在循环完成之前执行吗?函数不会被强制先执行循环然后返回语句吗?

function doSomethingRealWorkAsync() {
    var deferred = $q.defer();

    //loop through the items in an array and perform some heavy lifting that will take time

    deferred.resolve('Done!');
    return deferred.promise;
}

doSomethingRealWorkAsync().then(function(val) {
    console.log('Promise Resolved!', val);
});

我看过的每个示例都使用异步进程($timeout 或 setTimeout)来模拟正在完成的工作。真正的工作呢?如果我有多个要并行运行的长时间运行的进程怎么办?

使用上述模式会产生以下代码,但我无法想象它能正常工作。这行得通吗?如果不是,为什么?如果是,怎么办?

$scope.items = [{}];
$scope.initialized = false;

function doOneThingToItemsAsync() {
    var deferred = $q.defer();

    for (var i in items) {
        items[i].propertyA = 'this';
    }
    deferred.resolve('Done with One Thing!');
    return deferred.promise;
}

function doAnotherThingToItemsAsync() {
    var deferred = $q.defer();

    for (var i in items) {
        items[i].propertyB = 'that';
    }

    deferred.resolve('Done with Another Thing!');
    return deferred.promise;
}

function doYetAnotherThingToItemsAsync() {
    var deferred = $q.defer();

    for (var i in items) {
        items[i].propertyC = 'I smell a cat';
    }

    deferred.resolve('Done with Yet Another Thing!');
    return deferred.promise;
}

function getItems () {
    $http.get("/api/widgets", { timeout: 0 })
        .success(function (data) {
            items = data.items;
            $q.all([doOneThingToItemsAsync(), 
                    doAnotherThingToItemsAsync(),
                    doYetAnotherThingToItemsAsync()])
                .then(function(result) {
                    for (var i in result) {
                        console.log(result[i]);
                    }
                    initialized = true;
                });
        })
        .error(function (data) {
            if (data.errorMessage) {
                console.log("There was a problem retrieving your data: \n" + data.errorMessage + "\nPlease try again.");
            } else {
                console.log("There was a problem retrieving your data.  Please try again.");
            }
        });
}

浏览器的解释器是否评估函数返回的类型(在本例中为 promise)并允许您调用该类型的方法(例如 then、success、error)传递将在执行 deferred 时执行的回调函数.resolve、deferred.reject 等?

最佳答案

不,正如您已经意识到的那样,您需要确保在完成任何实际工作之前返回 promise 。所以在返回 promise 之前做内联工作是行不通的。

基本上这个想法是有一个内联函数,它只创建一个延迟对象并从中返回 promise ,然后有一个异步操作来完成实际工作,并且可以通过闭包访问延迟对象并可以设置它工作完成后解决。

所以你可以拿你的例子做这样的事情:

function doSomethingAsync() {
var deferred = $q.defer();

setTimeout(function() {
   // do the actual work
   deffered.resolve();
}, 500);

return deferred.promise;
}

doSomethingAsync().then(function() {
console.log('Promise Resolved! and work is done');
}); 

关于javascript - 如何使用 $q.all 跨多个异步函数处理 $http.get 的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25718828/

相关文章:

java - 如何将数据从不同的类添加到Arraylist

javascript - 使用 Nodejs 的 KafkaClient

javascript - 处理有效的模态解雇和真正的异常

jquery - Backbone.Model.save 和 Promise

javascript - $q.all 在 promise 被拒绝时解决

arrays - NodeJS - 使用 Q 对对象数组执行异步操作,但有所不同

javascript - Angular - 动态模块加载和编译

javascript - 我可以用数组或循环来收缩这段代码吗?

javascript - 唯一的对象数组并使用 lodash 或下划线合并重复项

javascript - 嵌套 promise 工作时无法获取 $q.all - 等待全部