代码之家  ›  专栏  ›  技术社区  ›  Simon Price

类型脚本:未捕获类型错误:此。fnName不是函数

  •  2
  • Simon Price  · 技术社区  · 6 年前

    我正在使用Typescript,有一个ajax调用,成功后调用另一个函数\方法。

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

    我得到的确切错误是

    未捕获类型错误:此。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 回复  |  直到 6 年前
        1
  •  2
  •   Kamil Kiełczewski    6 年前

    问题是在ajax回调中

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

    方法 this.deleteTheseSuccess 松开“this”上下文(因为ajax调用它)。

    您可以通过包含 this self 变量并将其传递给 dataAccess.ajaxCall

    编辑

    尝试这样的方法(我从head编写代码,所以要进行测试):

    将其添加到类中 PrintQueue 以下方法

    public deleteTheseSuccessWrapper() {
        let self = this;
        return () => { self.deleteTheseSuccess(); };
    }
    

    并将其用于 deleteThese 方法依据:

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

    编辑-版本2

    @埃斯特斯 在评论中指出: 为什么需要DeleteTheSuccessWrapper? 我们可以通过使用fat arrow来省略它:

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

    所以我们有 oneliner公司 解决方案-我从头开始编写上述代码,但我认为它也应该工作

        2
  •  2
  •   Estus Flask    6 年前

    deleteTheseError deleteTheseSuccess 方法作为回调传递。如相关 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) {...}
    ...