当我使用async / awaitfunction时,Angular UI路由器不处理parsing函数?

我一直在试图根据这篇文章呈现某个与状态和组件相关的模板

在我的项目下运行dev-server它一切正常,当我执行$state.go("home")组件模板加载我期望,但是当我在testing环境中这样做,这是行不通的。

在testing之前,当我使用“模板”而不是“组件”与ui-router一起使用“旧模式”时,执行$rootScope.$digest()就足以在<div ui-view></div>但使用这种新的方式,这不工作了。

我究竟做错了什么?

编辑 :我一直试图深入了解这个问题,我看到这个问题是与HTTP请求完成。 也许这与我的承诺使用async / awaitparsingcallback的方式有关。 请检查服务:

服务

 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() } }) } 

testing

 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 最后,我们发现问题,但我无法弄清楚真正的问题 。 我在我的项目中创build了一个分支来显示问题。 这与async/await javascriptfunction有关:

 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) // } } 

存储库

所以我的新问题是:

  • 为什么我使用asynchronous/等待function的方式,它与testing环境不兼容的UI路由器解决,但在生产代码工作?
  • 也许它与$ httpBackend.flush()调用有关?

编辑3在angular度UI路由器存储库中报告的问题3522

问题是angular度期望一个angular度的承诺这就是为什么你的工作,但你的等待不会,你可以通过使用库解决这个问题: https : //www.npmjs.com/package/angular-async-await或做一个像他们在这里演示的build设https://medium.com/@alSkachkov/using-async-await-function-in-angular-1-5-babel-6-387f7c43948c

祝你好运!

这只是一个受过教育的猜测,基于我对parsing器的工作方式和ngMock作用的理解。 在你的第一个例子中,你的getTodos resolvescheme在$http promise解决之前不会返回,此时你从响应中获取值并返回它。 但是,parsing器需要一个$q.Promise值作为一个$q.Promise来保存路由器的渲染,直到parsing完成。 在你的代码中,取决于它如何被转发, awaitreturn调用可能不会产生正确的哨兵值,所以它被视为一个同步响应。

一种testing方法是请求控制器中的resolve ,以查看您的todolist组件并检查其值。 我敢打赌,这不是一个$q.Promise ,虽然它可能是一个原生的诺言。

当使用resolve时,只需通过添加一个then链接Promise并将其返回即可。 路由器将处理其余的。

或者更好的,切换到Observable! (/我鸭子进来的西红柿)