首页 文章

为什么变量在方法中是未定义的,但它不在Typescript的构造函数中

提问于
浏览
1

我正在使用带有Typescript的1.4.9 Angularjs开发一个应用程序 .

我有一个注入了testManagementService服务的控制器,testManagementService变量是构造函数中的一个对象,但是在调用它的方法中它是未定义的 . 奇怪的是,我在另一个控制器与另一个服务有相同的设置,它工作正常 .

问题:

  • 构造函数中有一个带有标签testmgmgservice的console.log,它说testManagementService变量是一个具有getTestSuiteTree方法的Restangular对象

  • 控制台登录readRepository方法,由kendo.data.TreeListDataSource管理/管理,表示this.testManagementService未定义 .

enter image description here

到目前为止我做了什么:

  • 我检查了语法,有可能我错过了一些东西 - >没有

  • 我已经更改了变量名称,以检查是否有其他变量覆盖它 - >相同的结果

  • 我睡了很久,有时帮忙 - >没有新想法

  • 我用Vs2013和VS2015编译了代码 - >结果相同

the service

module sayusiando.gonogo.web.spa.service {
    import IGeneralTestSuitTestCaseContract = sayusiando.gonogo.web.spa.common.contracts.IGeneralTestSuitTestCaseContract;
    "use strict";

    export interface ITestManagementService {

        getTestSuitTree(): ng.IPromise<IGeneralTestSuitTestCaseContract[]>;

    }

    class TestManagementService implements ITestManagementService {

        //#region ctor
        constructor(
            private Restangular: restangular.IService
        ) { }
        //#endregion

        public getTestSuitTree(): ng.IPromise<IGeneralTestSuitTestCaseContract[]> {

            var resource = this.Restangular.all("TestSuite/GetTestSuiteTree");

            return <any>resource.getList();

        }

    }

    factory.$inject = ["Restangular"];

    function factory(Restangular: restangular.IService) {
        return new TestManagementService(Restangular);
    }

    angular
        .module("goNoGo")
        .factory("testManagementService", factory);

}

The controller

module sayusiando.gonogo.web.spa.mainpage.showtestsuittree.controllers {
    import IGeneralTestSuitTestCaseContract = sayusiando.gonogo.web.spa.common.contracts.IGeneralTestSuitTestCaseContract;
    import DataSourceTransport = kendo.data.DataSourceTransport;
    import DataSourceSchema = kendo.data.DataSourceSchema;
    import DataSourceSchemaModelFields = kendo.data.DataSourceSchemaModelFields;
    import TestManagementService = sayusiando.gonogo.web.spa.service.ITestManagementService;
    "use strict";

    export interface IShowTestSuitTreeController {
        activate: () => void;
    }

    class ShowTestSuitTreeController implements IShowTestSuitTreeController {

        //#region Variables
        testSuiteTree = [];
        testSuiteTreeKendoTreeListOptions: kendo.ui.TreeListOptions = {};
        //#endregion

        //#region Inject and ctor
        static $inject: string[] = ['testManagementService'];

        constructor(
            private testManagementService: gonogo.web.spa.service.ITestManagementService
        ) {

            console.log('testmgmgservice', testManagementService);

            this.activate();

        }
        //#endregion

        activate(): void {

            var dataSourceTransport = <DataSourceTransport>{
                read: this.readRepository
            };

            var schema: DataSourceSchema = <DataSourceSchema>{
                model: {
                    id: "id",
                    parentId: "parentId",
                    fields: <DataSourceSchemaModelFields>{

                        id: { type: "number", editable: false, nullable: true },
                        name: { type: "string", editable: false, nullable: true }

                    }

                }

            };

            var dataSource = new kendo.data.TreeListDataSource({
                transport: dataSourceTransport,
                schema: schema,
                batch: true
            });


            var idColumn: kendo.ui.TreeListColumn = <kendo.ui.TreeListColumn>{
                field: "id",
                width: "100px"
            };
            var nameColumn: kendo.ui.TreeListColumn = <kendo.ui.TreeListColumn>{
                field: "name",
                width: "400px"
            };

            this.testSuiteTreeKendoTreeListOptions.dataSource = dataSource;
            this.testSuiteTreeKendoTreeListOptions.sortable = false;
            this.testSuiteTreeKendoTreeListOptions.editable = false;
            this.testSuiteTreeKendoTreeListOptions.columns = [
                idColumn,
                nameColumn
            ];

        }

        readRepository(e): any {

            console.log('testmgmt2', this.testManagementService);
            this.testManagementService.getTestSuitTree().then((result: Array<IGeneralTestSuitTestCaseContract>): void => {
                e.success(result);
            }, (reason: any): void => {
                e.error(reason);
            });

            return e;
        }

    }

    angular
        .module("goNoGo")
        .controller("showTestSuitTreeController", ShowTestSuitTreeController);
}

The generated javascript from the controller

var sayusiando;
(function (sayusiando) {
    var gonogo;
    (function (gonogo) {
        var web;
        (function (web) {
            var spa;
            (function (spa) {
                var mainpage;
                (function (mainpage) {
                    var showtestsuittree;
                    (function (showtestsuittree) {
                        var controllers;
                        (function (controllers) {
                            "use strict";
                            var ShowTestSuitTreeController = (function () {
                                function ShowTestSuitTreeController(testManagementService) {
                                    this.testManagementService = testManagementService;
                                    //#region Variables
                                    this.testSuiteTree = [];
                                    this.testSuiteTreeKendoTreeListOptions = {};
                                    console.log('testmgmgservice', testManagementService);
                                    this.activate();
                                }
                                //#endregion
                                ShowTestSuitTreeController.prototype.activate = function () {
                                    var dataSourceTransport = {
                                        read: this.readRepository
                                    };
                                    var schema = {
                                        model: {
                                            id: "id",
                                            parentId: "parentId",
                                            fields: {
                                                id: { type: "number", editable: false, nullable: true },
                                                name: { type: "string", editable: false, nullable: true }
                                            }
                                        }
                                    };
                                    var dataSource = new kendo.data.TreeListDataSource({
                                        transport: dataSourceTransport,
                                        schema: schema,
                                        batch: true
                                    });
                                    var idColumn = {
                                        field: "id",
                                        width: "100px"
                                    };
                                    var nameColumn = {
                                        field: "name",
                                        width: "400px"
                                    };
                                    this.testSuiteTreeKendoTreeListOptions.dataSource = dataSource;
                                    this.testSuiteTreeKendoTreeListOptions.sortable = false;
                                    this.testSuiteTreeKendoTreeListOptions.editable = false;
                                    this.testSuiteTreeKendoTreeListOptions.columns = [
                                        idColumn,
                                        nameColumn
                                    ];
                                };
                                ShowTestSuitTreeController.prototype.readRepository = function (e) {
                                    console.log('testmgmt2', this.testManagementService);
                                    this.testManagementService.getTestSuitTree().then(function (result) {
                                        e.success(result);
                                    }, function (reason) {
                                        e.error(reason);
                                    });
                                    return e;
                                };
                                //#endregion
                                //#region Inject and ctor
                                ShowTestSuitTreeController.$inject = ['testManagementService'];
                                return ShowTestSuitTreeController;
                            })();
                            angular
                                .module("goNoGo")
                                .controller("showTestSuitTreeController", ShowTestSuitTreeController);
                        })(controllers = showtestsuittree.controllers || (showtestsuittree.controllers = {}));
                    })(showtestsuittree = mainpage.showtestsuittree || (mainpage.showtestsuittree = {}));
                })(mainpage = spa.mainpage || (spa.mainpage = {}));
            })(spa = web.spa || (web.spa = {}));
        })(web = gonogo.web || (gonogo.web = {}));
    })(gonogo = sayusiando.gonogo || (sayusiando.gonogo = {}));
})(sayusiando || (sayusiando = {}));
//# sourceMappingURL=showTestSuitTreeController.js.map

1 回答

  • 1

    我很确定问题是你在这里传递函数引用到框架:

    var dataSourceTransport = <DataSourceTransport>{
          read: this.readRepository
      };
    

    这样做,你正在失去上下文(这个) . 当库调用readRepository函数时,它不再适用于事先定义函数的上下文 . 因此,调用函数时 this 上不存在 testManagementService .

    您可以通过绑定到正确的上下文来解决此问题,如下所示:

    var dataSourceTransport = <DataSourceTransport>{
          read: this.readRepository.bind(this)
      };
    

    或者在传递参考时使用箭头功能捕获它

    var dataSourceTransport = <DataSourceTransport>{
          read: (e) => this.readRepository(e)
      };
    

    或者通过使回调成为箭头函数本身,保持注册原样 . 请注意其含义,因为该函数不再在原型上注册 .

    readRepository = (e) => {
        ...
    }
    

    有关详细信息,请查看https://basarat.gitbooks.io/typescript/content/docs/arrow-functions.html

相关问题