当我们需要回调几个metods时,$ q和promise的用法是什么

时间:2016-10-21 09:43:49

标签: angularjs amazon-web-services amazon-ec2

我正在使用angularJS并试图通过aws.sdk.js

创建亚马逊VPC

现在,当我创建VPC时,我必须完成各种配置,并在链

中调用以下方法
  1. 创建vpc () => vpc_
  2. 创建互联网网关() => igw_
  3. 附加互联网网关(vpc_, igw_) =>
  4. 创建子网(vpc_) => subnet_
  5. 创建路线表(vpc_) => rtb_
  6. 关联路线表(rtb_, subnet_) =>
  7. 创建安全组(vpc_) => sg_
  8. 添加入站规则(sg_) =>

  9. 另外为每个生成的资源创建标记。

  10. 你可以看到一些函数参数取决于之前的函数等等。我在每个AWS方法上使用$ q服务,但这变成了如此大的回调地狱。

    我还捕获了后面每个函数的通知,所以我的输入函数就像这样

    functionOne().then(function(res1) {
       console.info(res1);
       functionTwo(res1.id).then(res2) {
          console.info(res2);
           ......... series of functions within function....
            ----------------
            ----------------
            .then(res7) { functionEight(res7.id) {
            }, function (err) {}, function (notify) {})
            .finally(function(){ console.log('Finally done everything'); });
           ---------------------
           ---------------------
       }, function (err2) {
      console.error(err2);
      }, function (notify2) {
       console.log(nofify2);
      });
    }, function (err1) {
      console.error(err1);
    }, function (notify1) {
       console.log(nofify1);
    });
    

    我的功能签名如下

     functionX: function() {
                        var d = $q.defer();
                        var params = {
                            //...
                        };
                        ec2.anyMethodName(params, function(err, data) {
                            if (err) {
                                d.reject(err);
                            } else {
                                d.notify('Notifications methods');
                                d.resolve(data);
                            }
                        });
                        return d.promise;
                    }
    

    您可以在我的控制器here

    中看到方法的链接

    所以我的问题是

    • Amazon native thenable promise属性是否可以在角度中使用?如果是,那么我们如何实施通知?

    • 有没有分拣机方法呢?像错误将在最后捕获?使用$.all()但不是如何使用?

    • 如果我在functionOne上使用.finally()而不是在控制台中抛出错误 。最终不是函数

2 个答案:

答案 0 :(得分:1)

你为什么不

functionOne()
    .catch(errorHandlerOne)
    .then(functionTwo) // calls functionTwo(responseOne)
    .catch(errorHandlerTwo)
    .then(functionThree) // calls functionThree(responseTwo)
    .catch(errorHandlerThree)
    .finally(finalHandler)

修改:如果您想在functionOne中访问functionThree的结果,您可以执行以下操作:

functionTwo(resultOne) {
    var promise = d.promise;
    promise.then(function(resultTwo) {
       return [resultOne, resultTwo];
    });
  return d.promise
}

有关详细信息,请参阅this答案。

您无需必须编写匿名回调作为承诺解析和拒绝处理程序

您的回调将自动使用上一个函数中的已解决/拒绝承诺进行调用。

如果你希望你的整个链失败,如果任何一个承诺失败,你总是使用.all(),所以如果你想使用{{1}你应该注意的事情}}。

答案 1 :(得分:1)

将承诺,return值链接到成功处理程序; throw值为拒绝处理程序:

functionOne().then(function onSuccess(res1) {
    console.info(res1);
    //return promise to chain
    return functionTwo(res1.id);
}).catch(function onReject(error1) {
    console.log(error1)
    //throw to chain rejection
    throw error1;
}).then(function onSuccess2(res2) {
    console.info(res2);
    //return promise to chain
    return functionThree(res2.id);
}).then(function onSuccess3(res3) {
    console.info(res3);
    //return promise to chain
    return functionFour(res3.id);
}).then(function onSuccess4(res4) {
    console.info(res4);
    //return to chain
    return res4.id;
});

throw拒绝处理程序非常重要。如果拒绝处理程序只是执行控制台日志并省略throw语句,则该函数返回undefined并拒绝转换。处理的下一个成功将以undefined作为参数调用。

来自文档:

  

链接承诺

     

因为调用promise的.then方法会返回一个新的派生promise,所以很容易创建一个promise链。

     

可以创建任意长度的链,并且由于可以使用另一个承诺(将进一步推迟其解析)来解决承诺,因此可以在链中的任何点暂停/推迟承诺的解析。这使得实现强大的API

成为可能

- AngularJS $q Service API Reference -- Chaining Promises

有关详细信息,请参阅SO: Angular execution order with $q -- Chaining Promises

  

来自外部来源(例如AWS API)的承诺可以转换为$q.when的$ q服务。

var angularPromise = $q.when(AWS.request.promise());

来自DOCS:

  

     

将可能是值的对象或(第三方)随后的承诺包含到$q承诺中。当您处理可能会或可能不是承诺的对象,或者承诺来自不可信任的来源时,这非常有用。

- AngularJS $q Service API Reference -- $q.when