비동기 함수와 AngularJs 1.X가 혼합되지 않음
11079 단어 javascriptangular
Originally posted on ivantanev.com
최근에 AngularJS 1.x 프로젝트를 리팩토링하고 다음 코드를 작성했습니다.
// DO NOT USE THIS CODE, IT BREAKS ANGULARJS!
// Combining $http with async functions does not work in AngularJS 1.X
async function updateItem(item) {
const { data } = await $http.put(`/items/${item.id}`, item)
return data
}
위의 내용은 충분히 순진해 보이지만 Angular의 다이제스트 주기를 깨뜨립니다. 약속이 이행되면 페이지 업데이트가 표시되지 않습니다.
대신 무엇을 해야 합니까?
await/async
를 $http과 함께 사용하지 마십시오. 대신 .then()
와 함께 이전 약속 스타일을 사용하십시오.// Use promise.then() instead of async/await
function updateItem(item) {
return $http.put(`/items/${item.id}`, item).then(({ data }) => data)
}
위의 내용이 완전히 합리적이고 현대적인 JavaScript처럼 보일 수 있지만 이를 사용하려고 하면 Angular의 다이제스트 주기가 중단됩니다.
어디가 깨지나요?
브라우저가
async/await
코드를 실행할 때 수행하는 작업을 살펴보겠습니다.// DO NOT USE THIS CODE, IT BREAKS ANGULARJS!
// Combining $http with async functions does not work in AngularJS 1.X
// This function:
async function updateItem(item) {
const { data } = await $http.put(`/items/${item.id}`, item)
return data
}
// Is equivalent to the following code:
function updateItem(item) {
return Promise.resolve($http.put(`/items/${item.id}`, item)).then((value) => {
const { data } = value
return data
})
}
보시다시피
$q
에서 반환된 원래 $http.put()
약속은 새 Promise.resolve()
로 래핑됩니다. 이것은 AngularJS가 약속이 정착될 때 더 이상 추적할 수 없음을 의미합니다.컨트롤러에서 비동기 버전
updateItem()
을 사용하려고 하면 문제가 발생합니다.function SomeCtrl($scope, initialItem) {
$scope.item = initialItem
this.onClick = function() {
updateItem($scope.item)
.then(updatedItem => ($scope.item = updatedItem))
}
}
The
async function
implementation ofupdateItem()
would break the highlighted line. The changed$scope.item
variable will not be reflected in the DOM, or watchers, until a random digest cycle executes.
그 이유는 AngularJS가 일반 약속이 해결되는 시점을 알 수 없기 때문입니다.
AngularJS에는 브라우저 프리미티브($timeout, $interval 및 자체 Promise 라이브러리$q에 대한 특수 래퍼가 있습니다. AngularJS는 완료 시점을 추적하고 $rootScope.$digest() 주기를 실행하기 위해 이러한 비동기 인터페이스를 래핑해야 합니다.
async function
를 사용했을 때 우리는 setTimeout()
대신 $timeout()
를 직접 사용한 것과 같은 상황에 처해 있습니다. AngularJS가 비동기 함수 실행이 완료된 시점을 추적할 방법이 없습니다.컨트롤러에서
async function
가 작동하도록 하려면 $q.resolve()
로 다시 래핑해야 합니다.function SomeCtrl($q, $scope, initialItem) {
$scope.item = initialItem
this.onClick = function() {
$q.resolve(updateItem($scope.item)).then(
updatedItem => ($scope.item = updatedItem)
)
}
}
또는 컨트롤러 속성 할당 주위에 다른
async function
및 $apply()을 사용할 수 있습니다.function SomeCtrl($scope, initialItem) {
$scope.item = initialItem
this.onClick = async function() {
const updatedItem = await updateItem($scope.item)
$scope.$apply(() => {
$scope.item = updatedItem
})
}
}
async function
코드의 효과를 $scope.$apply()
로 수동으로 래핑하거나 $q.resolve()
로 약속을 래핑해야 합니다. 이것은 처음에 async/await
를 사용할 가치가 없습니다. async/await
인터페이스가 훨씬 더 좋기 때문에 여러 비동기 작업을 조정해야 할 때 이것은 불행한 일입니다.결론적으로
모던
async/await
함수는 훌륭하고 오래된 코드를 리팩토링할 때 사용하고 싶은 유혹이 있습니다. 그러나 AngularJS 1.X 프로젝트에서 번거롭게 할 가치는 없습니다. 대신 $q
약속 인터페이스를 고수해야 합니다.my website 에서 인사하거나 다른 게시물을 확인하세요.
즐거운 코딩!
Reference
이 문제에 관하여(비동기 함수와 AngularJs 1.X가 혼합되지 않음), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/vantanev/async-functions-and-angularjs-1-x-do-not-mix-3kb3텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)