angularjs:最终使用链式承诺

时间:2014-10-09 16:54:16

标签: javascript angularjs cordova promise

我对JavaScript开发很陌生,而且我很难绕过有角度的链接承诺。

我有一个案例,我从控制器调用服务来更新本地数据。更新完成后,无论是否成功,我都会继续在控制器内执行。

我的“调试信息”清楚地表明我的逻辑存在缺陷,但我不明白我的代码中的错误是什么。也许我不正确理解承诺。

以下是我正在使用的服务。我不关心promise结果的原因是它是混合Cordova应用程序的一部分,其中http响应由本机部分“后处理”,将数据持久保存到本地sqlite数据库。

'use strict';

angular.module('some-app').factory('scheduleService', function(
    $q, httpService, workingSiteService, dataAccessService) {

    var service = '/some-endpoint/?resourceId=';
    var scheduleService = {};

    /**
     * Get resource schedule from local db.
     *
     * @param   {Integer}   resource id
     * @returns {Promise}   resources schedule (bunch of workingsites)
     */
    scheduleService.getSchedule = function (resourceId) {
        console.log('getSchedule called');  // <- CONSOLE LOGGING
        return dataAccessService.getCollection({ collectionName: 'workingsite' }).then(function (workingsites) {
            return _.where(workingsites, { resourceId: resourceId });
        });
    };

    /**
     * Update resource schedule from service to local db.     
     * After update we can safely assume getSchedule returns as up-to-date data as possible.
     * 
     * @param   {Integer}   resource id
     * @returns {Promise}
     */
    scheduleService.updateSchedule = function (resourceId) {
        // see which workingsites we have in local db for given resource
        return this.getSchedule(resourceId).then(function (workingsites) {
            // map all workingsites' {id: id, version: version }, used as http request params
            var data = _.map(workingsites, function (workingsite) {
                return { id: workingsite.id, version: workingsite.version };
            });
            // post to service, this retrieves removed and modified workingsites' ids
            // contained within removed[] and modified[] arrays.
            // on http == 200, native proxy removes all workingsites from local db which are marked as removed
            return httpService.post(service + resourceId, data).then(function (response) {
                // get all modified workingsites' full information from "other" service, 
                // one by one. if http == 200, native proxy inserts/updates workingsites 
                // to local db
                return $q.all(_.map(response.modified, function (modified) {
                    return workingSiteService.get(modified.workingSiteId);
                })).then(function () {
                    console.log('updateSchedule called');  // <- CONSOLE LOGGING
                });
            });
        });
    };

    return scheduleService;
});

在我的控制器中,我有以下内容:

var schedule = scheduleService.updateSchedule(session.activeResourceId());
schedule.then(function () {
    console.log('then() block');    // <- CONSOLE LOGGING
});

schedule.catch(function () {
    console.log('catch() block');   // <- CONSOLE LOGGING
});

schedule.finally(scheduleService.getSchedule(session.activeResourceId).then(function (data) {
    console.log('finally() block'); // <- CONSOLE LOGGING
    ....

我希望调试信息按以下顺序排列:

getSchedule called
updateSchedule called
then() block
getSchedule called
finally() block

相反,我所拥有的是

enter image description here

1 个答案:

答案 0 :(得分:3)

据我所知,你几乎是对的。当您致电schedule.finally时,问题出在最后一行。

finally预计会收到thencatch之类的回调。在您的代码中,您再次调用scheduleService.getSchedule,然后立即调用它。这解释了日志输出中对scheduleService.getSchedule的两次并行调用。

所以正确的代码应该是:

schedule.finally(function() {
    scheduleService.getSchedule(session.activeResourceId).then(function (data) {
        console.log('finally() block'); // <- CONSOLE LOGGING
    })
});