简体   繁体   中英

angularjs: using finally with chained promises

I'm quite new to JavaScript development and I'm having hard time wrapping my head around angular chained promises.

I have a case where I call a service from controller to update local data. After update has been completed, whether it was successful or not, I'd continue execution inside controller.

My "debug information" is clearly showing my logic is flawed but I do not understand what's the bug in my code. Maybe I do not understand promises correctly.

Below is the service I'm using. Reason why I don't care about promise result is that it's part of hybrid Cordova application where http response is "post processed" by native parts, persisting data to local sqlite database.

'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;
});

In my controller, I have the following:

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
    ....

I'd expect the debug information to be in the following order:

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

Instead, what I have is

在此输入图像描述

As far as I can see you got it almost right. The problem is on the last line when you call schedule.finally .

finally expects a callback like then and catch . In your code you made a second call to scheduleService.getSchedule which then gets called immediately. This explains the two parallel calls to scheduleService.getSchedule in your log output.

So the correct code should be:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM