简体   繁体   English

AngularJS Promise链接$ q.all的最佳实践

[英]AngularJS Promise best practise for chaining $q.all

I'm new to writing and using promises and I'd like some advice. 我是写作和使用诺言的新手,我想要一些建议。 I have to chain my promises because some functions can only be run after others. 我必须遵守诺言,因为某些功能只能在其他功能之后才能运行。 I did used to handle this with a LOT of callback functions, which looked very messy and confusing. 我曾经用很多回调函数来处理这个问题,这些函数看起来非常混乱和混乱。 But with the chaining I'm doing... it's starting to look a bit messy again and I'm wondering whether I'm doing this correctly... 但是我正在使用链接...它开始看起来又有点混乱了,我想知道我是否正确地执行了此操作...

    function calcNetPriceSaleCharge(theItem) {
    var setInitialChargeAmount = miscSaleSvc.getInitialCharge(theItem);
    var setDiscountAmount = miscSaleSvc.getDiscountAmount(theItem);

    $q
        .all([setInitialChargeAmount, setDiscountAmount])
        .then(function(values) {
            theItem.initialchargeamount = values[0];
            theItem.initialdiscountamount = values[1];
        })
        .then(function() {
            var setActualCharge = miscSaleSvc.getActualCharge(theItem);
            var setVat = miscSaleSvc.setVat(theItem);
            $q
                .all([setActualCharge, setVat])
                .then(function(values) {
                    theItem.actualcharge = values[0];
                    theItem.vat = values[1];
                })
                .then(function() {
                    var setTotal = miscSaleSvc.getSaleTotal(theItem);

                    $q
                        .all([setTotal])
                        .then(function(values) {
                            theItem.total = values[0];
                        })
                        .catch(function(error) {
                            console.log(error);
                        });
                })
                .catch(function(error) {
                    console.log(error);
                });
        })
        .catch(function(error) {
            console.log(error);
        });
}

this does work but im not sure I'm going about this the right way! 这确实有效,但是我不确定我是否会采用正确的方式! An example function that is being called is this... 正在调用的示例函数是...

srv.getInitialCharge = function(theItem) {
    //set up the deferred var
    var deferred = $q.defer();

    var initialchargeamount = parseFloat(theItem.normalperiodcharge * theItem.quantity);

    if (isNaN(initialchargeamount)) {
        deferred.reject("Error when calculating Initial Charge Amount.");
    } else {
        //set up the failed result
        deferred.resolve(initialchargeamount);
    }

    //return the promise
    return deferred.promise;
};

Thanks in advance for your help :) 在此先感谢您的帮助 :)

You created a little callback hell which is exactly what Promises try to avoid. 您创建了一个小的回调地狱,这正是Promises试图避免的。 Remeber that you can also return a Promise inside then block to handle it further with then in the same chain of calls: Remeber,你也可以内返回无极then块来进一步处理它then在调用同一链:

function calcNetPriceSaleCharge(theItem) {
  var setInitialChargeAmount = miscSaleSvc.getInitialCharge(theItem);
  var setDiscountAmount = miscSaleSvc.getDiscountAmount(theItem);

  $q.all([setInitialChargeAmount, setDiscountAmount])
    .then(function(values) {
      theItem.initialchargeamount = values[0];
      theItem.initialdiscountamount = values[1];
    })
    .then(function() {
      var setActualCharge = miscSaleSvc.getActualCharge(theItem);
      var setVat = miscSaleSvc.setVat(theItem);
      return $q.all([setActualCharge, setVat]);
    })
    .then(function(values) {
      theItem.actualcharge = values[0];
      theItem.vat = values[1];
    })
    .then(function() {
      var setTotal = miscSaleSvc.getSaleTotal(theItem);
      return $q.all([setTotal]);
    })
    .then(function(values) {
      theItem.total = values[0];
    })
    .catch(function(error) {
      console.log(error);
    });
}

another variation: 另一个变化:

function calcNetPriceSaleCharge(theItem) {
  var setInitialChargeAmount = miscSaleSvc.getInitialCharge(theItem);
  var setDiscountAmount = miscSaleSvc.getDiscountAmount(theItem);

  return $q
    .all([setInitialChargeAmount, setDiscountAmount])
    .then(function(values) {
      theItem.initialchargeamount = values[0];
      theItem.initialdiscountamount = values[1];
    })
    .then(function() {
      var setActualCharge = miscSaleSvc.getActualCharge(theItem);
      var setVat = miscSaleSvc.setVat(theItem);
      return $q.all([setActualCharge, setVat]);
    })
    .then(function(values) {
      theItem.actualcharge = values[0];
      theItem.vat = values[1];
    })
    .then(function() {
      var setTotal = miscSaleSvc.getSaleTotal(theItem);
      return $q.all([setTotal]);
    })
    .then(function(values) {
      return (theItem.total = values[0]);
    });
}

calcNetPriceSaleCharge(something)
  .then(function(finalValue) {
    console.log(finalValue);
  })
  .catch(function(error) {
    console.log(error);
  });

Just for completeness sake a version using async/await syntax (Note, that this might not be available for older browsers ). 为了完整起见,使用async/await语法的版本(请注意,该版本可能不适用于较旧的浏览器 )。 For better readability the variable naming should be changed, however. 为了提高可读性,应更改变量命名。

async function calcNetPriceSaleCharge(theItem) {
  try {
    const setInitialChargeAmount = miscSaleSvc.getInitialCharge(theItem),
          setDiscountAmount = miscSaleSvc.getDiscountAmount(theItem);

    const values0 = await Promise.all( [setInitialChargeAmount, setDiscountAmount] );

    theItem.initialchargeamount = values0[0];
    theItem.initialdiscountamount = values0[1];

    const setActualCharge = miscSaleSvc.getActualCharge(theItem),
          setVat = miscSaleSvc.setVat(theItem);

    const values1 = await Promise.all( [setActualCharge, setVat] );

    theItem.actualcharge = values1[0];
    theItem.vat = values1[1];

    const values2 = await miscSaleSvc.getSaleTotal(theItem);

    theItem.total = values2;

  } catch ( e ) {
    console.log( e );
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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