$ http.post.then()期间AngularJS摘要周期没有触发

时间:2016-12-24 17:29:16

标签: angularjs angular-promise es6-promise angular-digest

使用 AngularJS 1.6.1 (ES6 / Babel)...控制器调用一个使用 $ http.post()的服务方法,所以我认为它会自动运行摘要。不得不添加$ timeout来强制它(更喜欢避免$ scope。$ apply,因为这是一个Angular组件,很快就会升级到AngularJS 2。)

有没有比我做的更好的方法?然后()关闭原来的$ http.post已经运行了摘要周期?如果我不包含$ timeout,则视图中不会更新任何内容。

下订单按钮提交表格,其ngClick为$ ctrl.placeOrder(结帐):

placeOrder(form) {
  if(form.$valid) {
    return this.Cart.placeOrder()
      .then(saleResponse => {
        // Page has {{ $ctrl.pageName }} but won't update without digest cycle
        this.pageName = 'Order Confirmation'; // displays confirmation
        form.$setPristine(); // treat the fields as untouched
        form.$submitted = false; // reset submitted state

        // Force a digest to run. Why is this needed?
        this.$timeout(() => this.pageName);
      })
      .catch(saleResponse => {
        form.$submitted = false;
        this.errorMessage = saleResponse.message;
        if(this.errorMessage.includes('card')) this.focusOnCardNumber();
      });
  }
}

这是Cart.placeOrder():

placeOrder() {
  // braintreeHostedFieldsTokenize() is a wrapper to return new Promise for their callback-based API
  return this.braintreeHostedFieldsTokenize(this.hostedFieldsInstance)
    .then(this.postOrderInformation.bind(this));
}

和Cart.postOrderInformation()

postOrderInformation(payload) {
  const orderInformation = {
    nonceFromClient: payload.nonce,
    purchaser: this.purchaser,
    recipient: this.recipient,
    cartItems: this.cartItems
  };

  return this.$http
    .post('/api/order', orderInformation)
    .then(orderResponse => {
      this.confirmation = orderResponse.data;
      if(!orderResponse.data.success) throw orderResponse.data;
      return this.confirmation;
    });
}

关于我可能出错的地方的任何想法都需要使用$ timeout?我的假设是$ http.post的then()将自己运行摘要周期,因为它是AngularJS。提前谢谢。

2 个答案:

答案 0 :(得分:2)

我的想法是.then Cart.placeOrder()方法正在Angular $ q服务库/队列外部的promise库/队列上执行。尝试使用$q.when将其移至$ q服务:

placeOrder(form) {
  if(form.$valid) {
    //return this.Cart.placeOrder()
    var promise = this.Cart.placeOrder();
    return $q.when(promise)
      .then(saleResponse => {
        // Page has {{ $ctrl.pageName }} but won't update without digest cycle
        this.pageName = 'Order Confirmation'; // displays confirmation
        form.$setPristine(); // treat the fields as untouched
        form.$submitted = false; // reset submitted state

        // Force a digest to run. Why is this needed?
        // this.$timeout(() => this.pageName);
      })

braintreeHostedFieldsTokenize()返回的承诺不是$ q服务承诺,因此没有与Angular摘要周期集成。

  

$ q.when

     

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

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

答案 1 :(得分:0)

我建议使用$ evalAsync而不是$ timeout。查看文档(https://docs.angularjs.org/api/ng/type/ $ rootScope.Scope)和此链接:AngularJS : $evalAsync vs $timeout