Angular UI 라우터가 비동기/대기 기능을 사용할 때 해결 기능을 처리하지 않습니까?
이 기사에 따라 상태 및 컴포넌트와 관련된 특정 템플릿을 렌더링하려고 합니다.
dev-server에서 실행되고 있는 프로젝트에서는 모든 것이 정상적으로 동작하며 실행 시$state.go("home")
컴포넌트 템플릿은 예상대로 로드되지만 테스트 환경에서 이 작업을 수행하면 작동하지 않습니다.
이전에 테스트에서 UI 라우터와 함께 "컴포넌트" 대신 "템플릿"을 사용하여 "이전 방식"을 사용할 경우,$rootScope.$digest()
템플릿 추가에 충분했습니다.<div ui-view></div>
하지만 이 새로운 방식으로는 더 이상 이 방법이 통하지 않습니다.
내가 뭘 잘못하고 있지?
편집: 문제를 자세히 이해하려고 노력했는데, 문제가 실행된 HTTP 요청과 관련이 있다는 것을 알게 되었습니다.비동기/대기 기능을 사용한 해결 콜백에서 약속이 해결되는 방식과 관련이 있을 수 있습니다.서비스를 확인해 주세요.
서비스
export class TodoService {
constructor($http, BASE_URL) {
this.http = $http;
this.url = `${BASE_URL}/todos`
}
async getTodos() {
const apiResponse = await this.http.get(this.url)
return apiResponse.data.todos
}
}
라우터
import '@uirouter/angularjs'
export function routes($stateProvider, $locationProvider) {
$locationProvider.html5Mode({
enabled: true,
requireBase: false,
rewriteLinks: true,
})
$stateProvider
.state("home", {
url: "/",
component: "todoList",
resolve: {
todosList: TodoService => TodoService.getTodos()
}
})
}
시험
import { routes } from "routes"
import { TodoListComponent } from "components/todoList.component"
import { TodoService } from "services/todo.service"
describe("TodoListComponent rendering and interaction on '/' base path", () => {
let componentDOMelement
let stateService
beforeAll(() => {
angular
.module("Test", [
"ui.router"
])
.config(routes)
.constant("BASE_URL", "http://localhost:5000/api")
.component("todoList", TodoListComponent)
.service("TodoService", TodoService)
//I enable this for better logs about the problem
.run(['$rootScope','$trace', function($rootScope, $trace) {
$trace.enable("TRANSITION")
}])
})
beforeEach(angular.mock.module("Test"))
beforeEach(inject(($rootScope, $compile, $state, $httpBackend) => {
//build the scene
//1st render the root element of scene: We needs a router view for load the base path
let scope = $rootScope.$new()
componentDOMelement = angular.element("<div ui-view></div>")
$compile(componentDOMelement)(scope)
scope.$digest()
document.body.appendChild(componentDOMelement[0]) //This is a hack for jsdom before the $rootScope.$digest() call
//2nd let's create a fake server for intercept the http requests and fake the responses
const todosResponse = require(`${__dirname}/../../stubs/todos_get.json`)
$httpBackend
.whenGET(/.+\/todos/)
.respond((method, url, data, headers, params) => {
return [200, todosResponse]
})
//3rd Let's generate the basic scenario: Go at home state ("/" path)
$state.go("home")
$rootScope.$digest()
$httpBackend.flush()
}))
it("Should be render a list", () => {
console.log("HTML rendered")
console.log(document.querySelectorAll("html")[0].outerHTML)
})
})
렌더링되지 않은 HTML 결과
<html>
<head>
<style type="text/css">
@charset "UTF-8";[ng\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate) {
display:none !important;
}
ng\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{
position:absolute;
}
</style>
</head>
<body><!-- uiView: -->
</body>
</html>
또한 HTML 이전에 stateChange를 추적했습니다.
console.log node_modules/@uirouter/core/_bundles/ui-router-core.js:1276
Transition #0-0: Started -> "Transition#0( ''{} -> 'home'{} )"
console.log node_modules/@uirouter/core/_bundles/ui-router-core.js:1282
Transition #1-0: Ignored <> "Transition#1( ''{} -> 'home'{} )"
console.log node_modules/@uirouter/core/_bundles/ui-router-core.js:1313
Transition #1-0: <- Rejected "Transition#1( ''{} -> 'home'{} )", reason: Transition Rejection($id: 0 type: 5, message: The transition was ignored, detail: "undefined")
과도기에 문제가 생겼지만 이유는 밝혀지지 않았다.
========================================================================
편집 2 마침내 문제를 발견했지만 진짜 문제를 파악할 수 없습니다.저는 문제를 보여주기 위해 프로젝트에 지점을 만들었습니다.이거랑 관련이 있어요async/await
javascript 기능:
export class TodoService {
constructor($http, BASE_URL) {
this.http = $http;
this.url = `${BASE_URL}/todos`
}
//Interchange the comment on the getTodos method and run `npm run tdd` for see the problem:
//When async/await doesn't used, the html associated to the resolve in the
// "/" route that used this service, the promise was resolved that expected.
//The idea for this branch it's research about the problem and propose a way
//for we can use async/await on the production code and on the testing environment
async getTodos() {
const apiResponse = await this.http.get(this.url)
return apiResponse.data.todos
}
// getTodos() {
// return this.http.get(this.url).then(res => res.data.todos)
// }
}
새로운 질문은 다음과 같습니다.
- 비동기/대기 기능을 사용하는 방식이 테스트 환경의 UI 라우터 해결과 호환되지 않지만 프로덕션 코드에서 작동하는 이유는 무엇입니까?
- $httpBackend와 관련이 있을 수 있습니다.flush() 콜?
편집 3 각도 UI 라우터 저장소에 문제 3522가 보고되었습니다.
문제는 angular가 각진 약속을 기대한다는 것입니다.그 때문에, 당신의 각진 약속은 효과가 있지만, 당신의 기다림은 효과가 없습니다.https://www.npmjs.com/package/angular-async-await와 같은 라이브러리를 사용하거나, https://medium.com/ @alSkachkov/using-async-awit-function-in-angular-1-5-bab-6-387f943c48c와 같은 구조를 사용하여 해결할 수 있습니다.
당신의 문제에 행운을 빌어요!
이것은 단지 내가 이해한 방법에 근거한 교육적인 추측일 뿐이다.resolve
-일하고뭐하는거죠?ngMock
「 」의 「 」를 참조해 주세요.resolve
★★★★★★에getTodos
$http
약속이 해결되었습니다.이 시점에서 응답에서 값을 추출하여 반환할 수 있습니다. ★★★★★★★★★★★★★★.resolve
- 되네 - 기대되네$q.Promise
라우터가 해결될 때까지 라우터의 렌더링을 유지하는 센티넬로서의 값., 「 」 「 」 「 」 「 」 「 」await
★★★★★★★★★★★★★★★★★」return
콜이 올바른 sentinel 값을 생성하지 않을 가능성이 높기 때문에 동기 응답과 같이 취급됩니다.
중 는 '하다'입니다.resolve
를) 위한 컨트롤러에서 사용합니다.todolist
컴포넌트 및 값을 검사합니다.물론 아닐 거야$q.Promise
약속하다
「」를 사용하고 resolve
, 「」, 「」를 하는 만으로 합니다then
합니다.이치노
또는 Observatibles로 전환하십시오! (/me ducking tomatoes)
언급URL : https://stackoverflow.com/questions/45863496/angular-ui-router-doesnt-process-the-resolve-function-when-i-use-async-await-fe
'programing' 카테고리의 다른 글
useEffect에서 종속 어레이를 제공하지 않는 것과 빈 어레이의 차이점은 무엇입니까? (0) | 2023.03.07 |
---|---|
AngularJS: 송신과 서버 응답 사이의 모든 폼 제어 비활성화 (0) | 2023.03.07 |
user_id만 사용하여 Wordpress에 로그인하는 방법 (0) | 2023.03.02 |
JSON 유형 내의 어레이 요소를 쿼리합니다. (0) | 2023.03.02 |
각도에서의 $timeout not defined 오류JS 앱 (0) | 2023.03.02 |