TypeScript:Uncaught TypeError:this.fnName不是函数

时间:2018-05-03 15:51:18

标签: javascript typescript

我正在使用Typescript并且有一个ajax调用,在Success上调用另一个函数\方法。

 deleteTheseSuccess(data) {
     new Fe.Upsm.Head().showGlobalNotification("Selected Items Deleted");
     this.refreshPrintQueueGrid(); <== this is there the error existst
     (window as any).parent.refreshOperatorPrintQueueCount();
 }

我上面指出的方法调用试图调用

refreshPrintQueueGrid() {
    $("#PrintQueueGrid").data("kendoGrid").dataSource.read();
    this.refreshPrintQueueStats();
}

这在VS2017中编译时没有任何问题,并相应地生成JavaScript文件

这是JavaScript输出中的调用

PrintQueue.prototype.refreshPrintQueueGrid = function () {
    $("#PrintQueueGrid").data("kendoGrid").dataSource.read();
    this.refreshPrintQueueStats();
};

我得到的确切错误是

  

未捕获的TypeError:this.refreshPrintQueueGrid不是函数。

如果有人能帮助我理解这里出了什么问题以及会导致什么问题,我将不胜感激,因为我会在我的应用程序的许多地方都有这个。

---编辑已编译的代码

PrintQueue.prototype.refreshPrintQueueGrid = function () {
            $("#PrintQueueGrid").data("kendoGrid").dataSource.read();
            this.refreshPrintQueueStats();
        }

---编辑2 - 班级

namespace Fe.Upsm {
export class PrintQueue {


    callingView: string

    constructor(callingView: string) {

        this.callingView = callingView;

        this.documentReadyObjects();

    }

    refreshPrintQueueGrid() {
        $("#PrintQueueGrid").data("kendoGrid").dataSource.read();
        this.refreshPrintQueueStats();
    }

    deleteThese(ids) {

        var jsonObj = {
            ids: ids
        }

        var dataAccess = new DataAccess.AjaxDataAccessLayer(Fe.Upsm.Enums.AjaxCallType.Post,
            Fe.Upsm.Enums.AjaxDataType.json,
            "../../PrintQueue/DeletePrintQueueItems",
            jsonObj);

        dataAccess.ajaxCall(this.deleteTheseError, this.deleteTheseSuccess);

    }

    deleteTheseSuccess(data) {
        new Fe.Upsm.Head().showGlobalNotification("Selected Items Deleted");
        this.refreshPrintQueueGrid;
        (window as any).parent.refreshOperatorPrintQueueCount();
    }

    deleteTheseError(xhr) {
        alert("An Error Occurred. Failed to delete print queue items");
    }



}

}

2 个答案:

答案 0 :(得分:1)

问题在于你的ajax回调

dataAccess.ajaxCall(this.deleteTheseError, this.deleteTheseSuccess);

方法this.deleteTheseSuccess松散&#39;这个&#39;上下文(因为ajax称之为)。

您可以将包含this作为self变量的其他人包装此函数,并将其传递给dataAccess.ajaxCall

修改

尝试这样的事情(我从头部编写代码以便测试它):

按照方法

将其添加到班级PrintQueue
public deleteTheseSuccessWrapper() {
    let self = this;
    return () => { self.deleteTheseSuccess(); };
}

并在deleteThese方法中使用它:

dataAccess.ajaxCall(this.deleteTheseError, this.deleteTheseSuccessWrapper());

编辑 - 第2版

@estus 在评论中指出:为什么需要deleteTheseSuccessWrapper?我们可以尝试通过使用fat-arrow来省略它:

dataAccess.ajaxCall(this.deleteTheseError, () => { this.deleteTheseSuccess() });

所以我们有 oneliner 解决方案 - 我从头开始编写上面的代码,但我认为它也应该有效

答案 1 :(得分:1)

deleteTheseErrordeleteTheseSuccess方法作为回调传递。正如相关umbrella question中所述,有一些方法可以将它们绑定到正确的this上下文。

可以将这些方法定义为箭头函数,但正如this answer所解释的那样,更通用的方法是将它们定义为原型方法并将它们绑定在类构造函数中:

constructor(callingView: string) {
    this.deleteTheseError = this.deleteTheseError.bind(this);
    this.deleteTheseSuccess = this.deleteTheseSuccess.bind(this);
    ...
}

除了箭头方法,TypeScript还提供了使用方法装饰器的选项,例如来自bind-decorator包。这为.bind(this)提供了更好的语法:

import bind from 'bind-decorator';

...
@bind
deleteTheseSuccess(data) {...}

@bind
deleteTheseError(xhr) {...}
...