为啥在带有 http 承诺的打字稿模块中未定义“this”

Posted

技术标签:

【中文标题】为啥在带有 http 承诺的打字稿模块中未定义“this”【英文标题】:why "this" is undefined in typescript module with http promise为什么在带有 http 承诺的打字稿模块中未定义“this” 【发布时间】:2016-02-24 10:08:36 【问题描述】:

这是我的第一次打字稿和角度尝试,但我遇到了一个问题。

我有一个按以下方式定义的模块控制器(.ts 文件):

module app.controllers 
    "use strict"

    import services = app.services;

    export class calendarController 

        calBlock: any;
        deptId: number;
        calSvc: app.services.calendarService;

        static $inject = ["$scope", "calendarService"];

        constructor(isolateScope: directives.calendarScope, calSvc: services.calendarService) 

            this.deptId = isolateScope.deptId;
            this.calSvc = calSvc;

            calSvc.getMonthBlock(12, 2015, 1, this.deptId)
            .then(
                function (response) 
                    //promise fullfilled (regardless of outcome)                
                    this.calBlock = response.data;
                 ,
                 function (error) 
                //handle errors
                    alert(error);
                    
             );
        
    

这是此控制器所依赖的服务:

module app.services 
    "use strict"
    export class calendarService 

        private _http: ng.IHttpService;

        static $inject = ["$http"];

        constructor(http: ng.IHttpService) 
            this._http = http;            
        

        getMonthBlock = function (month:number, year:number, calId:number, deptId:number) 

            //initialise service url
            var sURL = _sf.getServiceRoot('KrisisShifts') + "CalendarService/GetMonthCal/" + calId + "/" + deptId + "/" + month + "/" + year;
            //create config object for get function
            var config = 
                URL: sURL,
                method: "GET",
                dataType: 'json',
                headers: 
                    'ModuleId': _sf.getModuleId(),
                    'TabId': _sf.getTabId(),
                    'RequestVerificationToken': _sf.getAntiForgeryValue()
                
            
            //return the promise of the http.get function
            return this._http.get(sURL, config);

        
    

问题出现在控制器模块的下面一行:

this.calBlock = response.data;

问题在于 THIS 未定义,因此 calBlock 也未定义,jsConsole 会抛出错误:

TypeError:无法设置未定义的属性“calBlock” 在 shift-calendar-controller.js?cdv=28:14

我对 javascript、angular 和 typescript 比较陌生,所以我无法弄清楚为什么“this”未定义。我认为是因为它包含在一个函数中。

我需要一种方法将 reponse.data(来自 $http 调用的 json 数组)分配给我的控制器的 typescript 类的 calBlock 属性。有人可以帮我理解为什么 this 在响应函数中未定义以及我如何访问它?

谢谢

编辑:基于 tymeJV 答案的解决方案

这是重写的 calBlock 调用:

            calSvc.getMonthBlock(12, 2015, 1, this.deptId)
            .then((response) => 
                    //promise fullfilled (regardless of outcome)                
                    this.calBlock = response.data;
                ,
            (error) => 
                    //handle errors
                    alert(error);
                   
            );

【问题讨论】:

不幸的是,这对我不起作用。 【参考方案1】:

因为this 的上下文在回调中丢失了。在打字稿中使用箭头函数来保留上下文!

calSvc.getMonthBlock(12, 2015, 1, this.deptId).then((response) => 

)

【讨论】:

完美!感谢 tymeJV,我来自 windows wpf/mvvm(以艰难的方式学习嵌套上下文),所以我知道这是一个上下文问题,但只是不知道将上下文传播到函数中的约定。 @tymeJV 太好了。你能解释一下它为什么会这样吗? @NandaKumar - 见:basarat.gitbooks.io/typescript/content/docs/…

以上是关于为啥在带有 http 承诺的打字稿模块中未定义“this”的主要内容,如果未能解决你的问题,请参考以下文章

打字稿通用承诺返回类型

打字稿中的Angular js Http承诺

ts-node 执行带有模块导入和模块定义的打字稿

带有打字稿的角度材料设计

带有打字稿的VueJS单文件组件:找不到模块stuff.vue

为啥打字稿允许我覆盖一个空的状态对象?