【问题标题】:How to check the state of an angular-promise?如何检查角度承诺的状态?
【发布时间】:2019-06-16 03:51:57
【问题描述】:

在我的网站中,我有用于 twitter 和 facebook 的 API,它启用了“提及”功能(每当我们使用 @ 符号时就会弹出该功能)

但是,某些功能的访问令牌通常会过期,从而导致 API 无法正常工作。我将所有 API 存储在一个数组中,然后我需要检查令牌是否失败或未导致解决或拒绝 API 承诺。

这是一个较旧的代码,由于 $q.all 需要更改。由于 $q.all 会在所有承诺都得到解决时起作用,从而触发 .then() 调用,这会导致 .then() 函数在我的情况下永远不会工作(因为 Facebook API 永远不会工作)

我需要找到一个条件,检查每个 API 并且 .then() 仅针对已解析的 API(在本例中为 Twitter)运行并忽略失败的 API(在本例中为 Facebook)


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

【问题讨论】:

    标签: angularjs angular-promise


    【解决方案1】:

    我认为您正在寻找链接备份响应以捕获 api 错误并在等待“所有”它们之前在每个特定 api 调用上返回一个新的成功解决承诺。

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

    希望这会有所帮助。

    【讨论】:

    • 如果我问了一个不明智的问题,请原谅我;我只是 angularjs 的初学者,我仍在尝试围绕 API 概念进行思考,但我应该如何处理“handleTwiterSuccess”和“handleApiFailure”。是否有任何内置方法或者我必须为它显式编写函数?
    • 另外,apiCalls 是指 usersApi?
    • 这些只是您的实现函数或匿名函数的填充名称。如果您需要特定于 twitter/facebook 等的自定义成功处理,handleApiFailure 也是您编写的自定义函数。重要的是 handleApiFailure 或匿名函数返回 Promise.resolve 而不是 Promise.reject。这样 Promise.all 就会得到解决。
    • 是的,apiCalls 只是我为你的 usersApi 取的名字
    • 我不确定我是否遵循。 'handleApiFailure' 将失败的 Promise 转换为返回 null 而不是错误的成功 Promise。然后 Promise.all 获得的所有承诺都成功解决,但返回一些您可以过滤的空值。
    【解决方案2】:

    $q.all没有弹性1

    如果其中一个承诺被拒绝,$q.all 将被拒绝并出现第一个错误。

    要创建一个弹性复合promise,即等待所有promise完成通过或失败的promise,请在每个单独的promise上使用.catchconvert被拒绝的承诺到成功的承诺。

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

    从这个答案中可以看出两点:

    1. $q.all 承诺没有弹性。第一个被拒绝的 Promise 被拒绝。
    2. 可以通过向.then 方法或.catch 方法的onRejected 函数返回一个值,从被拒绝的promise 创建一个已履行的promise。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-27
      • 2020-08-17
      • 2016-10-03
      • 1970-01-01
      • 1970-01-01
      • 2015-11-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多