skip to Main Content

In my website, I have API’s for twitter and facebook which enables the “mentions” feature (the one that pops up whenever we use the @ symbol)

However, it is often that the access token for some feature is often expires resulting in the API not working. I store all my API’s in an array and then I need to check if the token has failed or not resulting in resolved or rejected API promise.

This is an older code that needs changing due $q.all. As $q.all works whenever all the promises have been resolved, thus triggering the .then() call, this results in the .then() function NEVER working in my case (as the Facebook API is never working)

I need to find a condition where each API is checked and the .then() runs for only that API that is resolved (twitter in this case) and ignores the failed API (Facebook in this case)


        if (selectedIds.allowed.TW) {
          usersApi.push(TS.loginResource.getTwitterProfiles({
            subUserId: selectedIds.allowed.TW,
            name: searchTerm
          }).$promise);
        }

        if (selectedIds.allowed.FB || selectedIds.allowed.FB_PAGE || 
            selectedIds.allowed.FB_GROUP) {
          $scope.post.showTags = true;
          usersApi.push(TS.loginResource.getFbPages({
            subUserId: selectedIds.allowed.FB_PAGE || selectedIds.allowed.FB 
            || selectedIds.allowed.FB_GROUP,
            name: searchTerm
          }).$promise);
        }


        if (usersApi.length) {
          $q.all(usersApi).then(function (responses) {
            var tags1 = responses[0];
            tags1.forEach(function (tag, i) {
              tags1[i].name = tag.name.replace(/"/g, "");
            });
            $scope.post.tags = tags1;
            if (usersApi.length > 1) {
              var tags2 = responses[1]
              tags2.forEach(function (tag, i) {
                tags2[i].name = tag.name.replace(/"/g, "");
              });
              $scope.post.tags = $scope.post.tags.concat(tags2);
            }
          })
        }
      }, 500);
    } else {
      $scope.post.tags = [];
      $scope.post.showTags = false;
    }

2

Answers


  1. I think you are looking to chain backup response that catch the api error and return a new success resolved promise on each specific api call before you wait on “all” of them.

    apiCalls.push(doTwiterStuff().then(handleTwiterSuccess, handleApiFailure);
    apiClass.push(doFBStuff().then(handleFbSuccess, handleApiFailure);
    
    Promise.all(apiCalls).then(arr => {
      arr.filter(x => !isNil(x)).forEach(x => doSomethingWithApiResult(x));
    });
    
    function handleApiFailure(x) {
      ...
      return Promise.resolve(null);
    }
    

    Hopes this helps.

    Login or Signup to reply.
  2. $q.all is not resilient1

    If one of the promises is rejected, the $q.all is rejected with the first error.

    To create a resilient composite promise, that is a promise that waits for all the promises to complete pass or fail, use .catch on each individual promise to convert the rejected promise to a successful promise.

    var resilientPromises = [];
    
    angular.forEach(promises, function(p) {
        var resilientP = p.catch( function(result) {
            //return to convert rejection to success
            return result;
        });
        resilientPromises.push(resilientP);
    });
    
    $q.all(resilientPromises).then( function (results) {
        //process results
    });
    

    The two things to take away from this answer:

    1. A $q.all promise is not resilient. It is rejected with the first rejected promise.
    2. A fulfilled promise can be created from a rejected promise by returning a value to the onRejected function of either the .then method or the .catch method.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search