mon*_*oh_ 26 angularjs typescript angularjs-scope
我正在使用Typescript 2.1(开发人员版本)将async/await转换为ES5.
我注意到在我更改了在异步函数中绑定查看的任何属性后,视图不会使用当前值更新,所以每次我必须在函数结束时调用$ scope.$ apply().
示例异步代码:
async testAsync() {
await this.$timeout(2000);
this.text = "Changed";
//$scope.$apply(); <-- would like to omit this
}
Run Code Online (Sandbox Code Playgroud)
此后text,视图中不会显示新值.
是否有任何解决方法,所以我不必每次手动调用$ scope.$ apply()?
Chr*_*ris 10
这里的答案是正确的,因为AngularJS不知道该方法,因此您需要"告诉"Angular有关已更新的任何值.
就个人而言,我会使用$q异步行为而不是使用await它作为"Angular方式".
你可以很容易地用$ q包装非Angular方法,即[注意这是我如何包装所有Google Maps函数,因为它们都遵循传递回调的模式以通知完成]
function doAThing()
{
var defer = $q.defer();
// Note that this method takes a `parameter` and a callback function
someMethod(parameter, (someValue) => {
$q.resolve(someValue)
});
return defer.promise;
}
Run Code Online (Sandbox Code Playgroud)
然后你可以像这样使用它
this.doAThing().then(someValue => {
this.memberValue = someValue;
});
Run Code Online (Sandbox Code Playgroud)
但是,如果您确实希望继续await使用$apply,那么在这种情况下,有一种比使用更好的方法$digest.像这样
async testAsync() {
await this.$timeout(2000);
this.text = "Changed";
$scope.$digest(); <-- This is now much faster :)
}
Run Code Online (Sandbox Code Playgroud)
$scope.$digest在这种情况下,因为更好的$scope.$apply将执行脏检查(用于变化检测Angulars法)对所有范围所有绑定值,这可能是昂贵的性能明智的-特别是如果你有很多的绑定.$scope.$digest但是,它只会检查当前的绑定值,$scope使其更具性能.
这可以通过angular-async-await扩展方便地完成:
class SomeController {
constructor($async) {
this.testAsync = $async(this.testAsync.bind(this));
}
async testAsync() { ... }
}
Run Code Online (Sandbox Code Playgroud)
可以看出,它所做的只是使用$rootScope.$apply()随后调用的包装器包装promise-returns函数.
没有可靠的方法在async函数上自动触发摘要,这样做会导致黑客攻击框架和Promise实现.没有办法为本机async函数(TypeScript es2017目标)执行此操作,因为它依赖于内部承诺实现而不是Promise全局.更重要的是,这种方式是不可接受的,因为这不是默认情况下预期的行为.开发人员应完全控制它并明确指定此行为.
鉴于testAsync被多次调用,并且它被调用的唯一地方是testsAsync,自动摘要testAsync最终将导致消化垃圾邮件.虽然正确的方法是在之后触发一次摘要testsAsync.
在这种情况下$async,仅适用于testsAsync而不适用于testAsync自身:
class SomeController {
constructor($async) {
this.testsAsync = $async(this.testsAsync.bind(this));
}
private async testAsync() { ... }
async testsAsync() {
await Promise.all([this.testAsync(1), this.testAsync(2), ...]);
...
}
}
Run Code Online (Sandbox Code Playgroud)
我已经检查了angular-async-await的代码,似乎他们正在使用$rootScope.$apply()异步承诺解决后来消化表达式。
这不是一个好方法。您可以使用 AngularJS 原版,$q并通过一个小技巧,您可以达到最佳性能。
首先,创建一个函数(例如,工厂,方法)
// inject $q ...
const resolver=(asyncFunc)=>{
const deferred = $q.defer();
asyncFunc()
.then(deferred.resolve)
.catch(deferred.reject);
return deferred.promise;
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以在您的实例服务中使用它。
getUserInfo=()=>{
return resolver(async()=>{
const userInfo=await fetch(...);
const userAddress= await fetch (...);
return {userInfo,userAddress};
});
};
Run Code Online (Sandbox Code Playgroud)
这与使用 AngularJS$q和最少的代码一样有效。
有没有任何解决方法,这样我就不必每次都手动调用 $scope.$apply() ?
这是因为 TypeScript 使用浏览器本机 Promise实现,而这不是 Angular 1.x 所了解的。要对其不控制的所有异步函数进行脏检查,必须触发摘要周期。