Typscript async/ait가 Angular를 업데이트하지 않음JS 뷰
Typescript 2.1(개발자 버전)을 사용하여 비동기/대기 상태를 ES5로 변환하고 있습니다.
비동기 함수로 표시되어야 하는 속성을 변경한 후 뷰가 현재 값으로 업데이트되지 않으므로 매번 $scope를 호출해야 합니다.함수의 끝에 $syslog()가 표시됩니다.
비동기 코드 예시:
async testAsync() {
await this.$timeout(2000);
this.text = "Changed";
//$scope.$apply(); <-- would like to omit this
}
새로운 ★★★★★★★★★★★★★★★★★★★.text
값이 이 후 뷰에 표시되지 않습니다.
$scope에 수동으로 전화할 필요가 없는 회피책이 있습니까?매번 $syslog()?
여기의 답은 앵귤러에서 정확합니다.JS는 방법에 대해 모르므로 업데이트된 값에 대해 Angular에 '알려야 합니다.
는 ★★★★★★★★★★★★★★★★★★★★★★★★★★.$q
에 대해서, 「」를 사용하는 것이 ,await
방식으로요.앵귤러 웨이'라고 합니다.
비 Angular 메서드는 $q로 쉽게 래핑할 수 있습니다.[모든 Google 지도 함수는 완료 통보를 받기 위해 콜백을 통과하는 패턴을 따르기 때문에 이렇게 포장합니다]
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;
}
그러면 이렇게 사용할 수 있습니다.
this.doAThing().then(someValue => {
this.memberValue = someValue;
});
, 하다, 하다, 하다, 하다.await
하는 보다 더 방법이 있다$apply
「」, 「」를 사용하는 $digest
. 이렇게
async testAsync() {
await this.$timeout(2000);
this.text = "Changed";
$scope.$digest(); <-- This is now much faster :)
}
$scope.$digest
때 더 요. 왜냐하면$scope.$apply
는 모든 스코프의 모든 바인드 값에 대해 더티 체크(변경 검출을 위한 각도 방식)를 수행합니다.이는 특히 바인딩이 많은 경우 고가의 퍼포먼스가 될 수 있습니다. $scope.$digest
는 의 「」, 「」, 「」, 「」의 범위내의 합니다.$scope
훨씬 더 퍼포먼스가 뛰어납니다.
이것은, 내선 번호에 의해서 간단하게 실시할 수 있습니다.
class SomeController {
constructor($async) {
this.testAsync = $async(this.testAsync.bind(this));
}
async testAsync() { ... }
}
보시다시피 약속 반환 기능을 나중에 호출하는 래퍼로 감싸는 것이 전부입니다.
를 자동적으로 하는 할 수 있는 .async
가 모두 됩니다.Promise
원어민에게는 할 수 있는 .async
TypeScript)es2017
target하며, "target"은 "target"이 아니기 Promise
이 으로 예상되는 동작이 때문에 수 없다는 입니다.더 중요한 것은 이 방법은 기본적으로 예상되는 동작이 아니기 때문에 받아들일 수 없다는 것입니다.개발자는 이를 완전히 제어하고 이 동작을 명시적으로 할당해야 합니다.
testAsync
번 , 되는 유일한 는 ""입니다.testsAsync
의, "Diagnost"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), ...]);
...
}
}
각도 비동기 대기의 코드를 조사해 보니$rootScope.$apply()
비동기 약속이 해결된 후 표현을 다이제스트합니다.
이치노Angular Angular를할 수 . 오리지널 JS ★★$q
약간의 트릭으로 최고의 퍼포먼스를 얻을 수 있습니다.
먼저 기능(공장, 방법 등)을 만듭니다.
// inject $q ...
const resolver=(asyncFunc)=>{
const deferred = $q.defer();
asyncFunc()
.then(deferred.resolve)
.catch(deferred.reject);
return deferred.promise;
}
이제 인스턴스 서비스용으로 에서 사용할 수 있습니다.
getUserInfo=()=>{
return resolver(async()=>{
const userInfo=await fetch(...);
const userAddress= await fetch (...);
return {userInfo,userAddress};
});
};
이는 Angular를 사용하는 것만큼 효율적입니다.JS$q
소한최
네이티브 ES6는 @basarat이 말했듯이Promise
다이제스트 사이클을 모르기 때문에
해서 가 타이프스크립트를 사용하게 할 수 .$q
ES6에 대해서입니다.
발음을 하지 될 것 같아요.$scope.$apply()
angular.module('myApp')
.run(['$window', '$q', ($window, $q) => {
$window.Promise = $q;
}]);
내가 원하는 행동을 보여주는 바이올린을 설치했어.여기서 알 수 있다: 각진과의 약속JS. 1000ms 후에 해결되는 Promise, 비동기 함수 및 Promise.race를 사용하고 있으며 여전히 4개의 다이제스트 사이클만 필요합니다(콘솔 열기).
원하는 행동이 무엇이었는지 다시 한 번 말씀드리겠습니다.
- 네이티브 JavaScript와 마찬가지로 비동기 기능을 사용할 수 있도록 합니다.이것은 다른 서드파티 라이브러리가 없다는 것을 의미합니다.
$async
- 최소 다이제스트 사이클 수를 자동으로 트리거합니다.
이것은 어떻게 달성되었습니까?
ES6에서는 Proxy라는 멋진 기능이 제공되었습니다.이 개체는 기본 작업(예: 속성 검색, 할당, 열거, 함수 호출 등)에 대한 사용자 지정 동작을 정의하는 데 사용됩니다.
즉, Promise를 Proxy로 랩할 수 있으며, Promise가 해결되거나 거부되면 필요한 경우에만 다이제스트 사이클이 트리거됩니다.다이제스트 사이클을 트리거하는 방법이 필요하기 때문에 이 변경은 Angular에 추가됩니다.JS 실행 시간
function($rootScope) {
function triggerDigestIfNeeded() {
// $applyAsync acts as a debounced funciton which is exactly what we need in this case
// in order to get the minimum number of digest cycles fired.
$rootScope.$applyAsync();
};
// This principle can be used with other native JS "features" when we want to integrate
// then with AngularJS; for example, fetch.
Promise = new Proxy(Promise, {
// We are interested only in the constructor function
construct(target, argumentsList) {
return (() => {
const promise = new target(...argumentsList);
// The first thing a promise does when it gets resolved or rejected,
// is to trigger a digest cycle if needed
promise.then((value) => {
triggerDigestIfNeeded();
return value;
}, (reason) => {
triggerDigestIfNeeded();
return reason;
});
return promise;
})();
}
});
}
★★async functions
「Promise to work」(약속)에 의존해, 몇줄의 코드로 소기의 동작을 실현했습니다.추가 기능으로 기본 Promise를 Angular로 사용할 수 있습니다.JS!
나중에 편집:이 동작은 일반 JS를 사용하여 복제할 수 있으므로 프록시를 사용할 필요가 없습니다.여기 있습니다.
Promise = ((Promise) => {
const NewPromise = function(fn) {
const promise = new Promise(fn);
promise.then((value) => {
triggerDigestIfNeeded();
return value;
}, (reason) => {
triggerDigestIfNeeded();
return reason;
});
return promise;
};
// Clone the prototype
NewPromise.prototype = Promise.prototype;
// Clone all writable instance properties
for (const propertyName of Object.getOwnPropertyNames(Promise)) {
const propertyDescription = Object.getOwnPropertyDescriptor(Promise, propertyName);
if (propertyDescription.writable) {
NewPromise[propertyName] = Promise[propertyName];
}
}
return NewPromise;
})(Promise) as any;
Angular에서 업그레이드하는 경우ngUpgrade를 사용하여 JS에서 Angular로 이동(https://angular.io/guide/upgrade#upgrading-with-ngupgrade):
Zone.js는 네이티브 약속에 패치를 적용하므로 모든 $q 기반 Angular 재작성을 시작할 수 있습니다.JS는 Microtask 큐가 비어 있을 때(예: Promise가 해결되었을 때) 자동으로 $digest를 트리거하므로 기본 Promise에 약속합니다.
Angular로 업그레이드 할 계획이 없는 경우에도 프로젝트에 Zone.js를 포함시키고 ngUpgrade와 같은 훅을 설정함으로써 동일한 작업을 수행할 수 있습니다.
$scope에 수동으로 전화할 필요가 없는 회피책이 있습니까?매번 $syslog()?
이는 TypeScript가 브라우저 네이티브를 사용하기 때문입니다. Promise
앵글 1.x로 하다제어하지 않는 모든 비동기 함수를 더티 체크하려면 다이제스트 사이클을 트리거해야 합니다.
@basarat가 말했듯이 ES6 Promise는 다이제스트 사이클을 모른다.당신은 약속해야 한다.
async testAsync() {
await this.$timeout(2000).toPromise()
.then(response => this.text = "Changed");
}
이미 설명한 바와 같이 angular는 언제 네이티브 Promise가 완료되었는지 알 수 없습니다. ★★★★★async
는 새로운 .Promise
.
생각할 수 있는 해결책은 다음과 같습니다.
window.Promise = $q;
이 방법으로 TypeScript/Babel은 각진 약속을 대신 사용합니다.그것은 안전한가요?솔직히 잘 모르겠어요.아직도 이 솔루션을 테스트하고 있어요.
일반적인 공장에서 변환 함수를 작성하려고 합니다(이 코드는 테스트하지 않았지만 작동해야 합니다).
function toNgPromise(promise)
{
var defer = $q.defer();
promise.then((data) => {
$q.resolve(data);
}).catch(response)=> {
$q.reject(response);
});
return defer.promise;
}
이건 단지 당신을 시작하기 위한 것일 뿐이지만, 결국 변환이 이렇게 간단하지는 않을 거라고 생각합니다.
언급URL : https://stackoverflow.com/questions/39943937/typescript-async-await-doesnt-update-angularjs-view
'programing' 카테고리의 다른 글
Angularjs 지시어:격리된 범위 및 특성 (0) | 2023.03.06 |
---|---|
바이트 어레이를 JSON에 배치하거나 그 반대도 마찬가지입니다. (0) | 2023.03.06 |
WooCommerce - URL에서 제품 및 제품 카테고리를 삭제하는 방법 (0) | 2023.03.01 |
React를 통한 빅리스트 퍼포먼스 (0) | 2023.03.01 |
문의폼7 - 커스텀 검증 (0) | 2023.03.01 |