AngularJS 摘要循环在 $http.post.then() 期间未触发
AngularJS digest cycle not firing during $http.post.then()
使用AngularJS 1.6.1 (ES6/Babel)...控制器调用一个使用$[=的服务方法34=]() 所以我认为它会自动 运行 摘要。不得不添加 $timeout 来强制它(最好避免 $scope.$apply 因为这是一个 Angular 组件,很快就会升级到 AngularJS 2)。
是否有比我所做的更好的方法?原本是 $http.post 的 then() 应该有 运行 摘要循环吗?如果我不包括 $timeout,则视图中不会更新任何内容。
下订单 按钮提交一个表单,其 ngClick 为 $ctrl.placeOrder(checkout):
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。提前致谢。
我建议使用 $evalAsync 而不是 $timeout。检查文档 (https://docs.angularjs.org/api/ng/type/$rootScope.Scope) and this link: AngularJS : $evalAsync vs $timeout
我的想法是 Cart.placeOrder()
的 .then
方法是在 Angular $q 服务 [=24= 外部的承诺 library/queue 上执行的].尝试使用 $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
Wraps an object that might be a value or a (3rd party) then-able promise into a $q
promise. This is useful when you are dealing with an object that might or might not be a promise, or if the promise comes from a source that can't be trusted.
使用AngularJS 1.6.1 (ES6/Babel)...控制器调用一个使用$[=的服务方法34=]() 所以我认为它会自动 运行 摘要。不得不添加 $timeout 来强制它(最好避免 $scope.$apply 因为这是一个 Angular 组件,很快就会升级到 AngularJS 2)。
是否有比我所做的更好的方法?原本是 $http.post 的 then() 应该有 运行 摘要循环吗?如果我不包括 $timeout,则视图中不会更新任何内容。
下订单 按钮提交一个表单,其 ngClick 为 $ctrl.placeOrder(checkout):
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。提前致谢。
我建议使用 $evalAsync 而不是 $timeout。检查文档 (https://docs.angularjs.org/api/ng/type/$rootScope.Scope) and this link: AngularJS : $evalAsync vs $timeout
我的想法是 Cart.placeOrder()
的 .then
方法是在 Angular $q 服务 [=24= 外部的承诺 library/queue 上执行的].尝试使用 $q.when
:
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
Wraps an object that might be a value or a (3rd party) then-able promise into a
$q
promise. This is useful when you are dealing with an object that might or might not be a promise, or if the promise comes from a source that can't be trusted.