Typescript中的移除事件监听器无效。

3

我在我的ionic 3聊天应用程序中尝试使用import { SMS } from '@ionic-native/sms';。但是document.removeEventListener('onSMSArrive');无法正常工作。

以下是我正在使用的软件包

"@ionic-native/sms": "^4.3.0",
"@ionic-native/core": "^4.3.0",
"cordova-sms-plugin": "^0.1.11",

问题在于当我第一次进入页面时,它完美地工作并在手机接收短信时接收消息。但是,如果我返回到另一页,然后再回到该页,在我的函数中我会收到相同的消息两次。我认为事件监听器没有被删除,当我再次导航到页面时,另一个监听器被添加到文档中。
以下是我的代码:
当页面加载时,我添加事件监听器,当页面卸载时,我将其删除。
public ionViewWillEnter() {
    this.smsService.startMessageListner();
}

public ionViewWillLeave() {
    this.smsService.stopMessageListner();
}

这是我的服务中的startMessageListner()stopMessageListner()函数。

public startMessageListner()
{
    --- some works do here ---
    this.startListner();
}

public startListner()
{
    this.recieveMessage().then((message) => {
        --- receives message here and when after 
            navigating multiple times I receives 
            multiple same messages here---
    }
}

public recieveMessage() {

    if (!window.SMS) { alert('SMS plugin not ready'); return; }

    window.SMS.startWatch(function() {
        console.log('Watching');
    }, function() {
        console.log('Not Watching');
    });

    this.promise = new Promise((resolve, reject) => {
        document.addEventListener('onSMSArrive', this.resolveMessage(resolve));
    });

    return this.promise;
}

public stopMessageListner()
{
    --- some works do here ---
    this.stopReciveMessage();
}

public stopReciveMessage()
{
    // ***This one also not works***
    // document.removeEventListener('onSMSArrive', (event)=>{
    //     window.SMS.stopWatch(function() {
    //         console.log('Stop Watching');
    //     }, function() {
    //         console.log('Not Stop Watching');
    //     });
    // });

    document.removeEventListener('onSMSArrive');

    window.SMS.stopWatch(function() {
        console.log('Stop Watching');
    }, function() {
        console.log('Not Stop Watching');
    });
}

请帮助我解决这个问题。这个问题浪费了我一整个星期,但是还没有解决。 :(

===更新评论===

所有给定的链接都说我必须在删除事件侦听器时传递完全相同的函数。在我的情况下,当我调用document.addEventListener时,我使用this.resolveMessage(resolve)resolve参数,所以我已经尝试过以下方法,但仍未解决。

  1. public recieveMessage() {
    
        --same content as above--
    
        let self = this; // I added this line for safe side
        this.promise = new Promise((resolve, reject) => {
            self.resolve = resolve;
            document.addEventListener('onSMSArrive', self.resolveMessage(resolve),false);
        });
    
        return this.promise;
    }
    
    public stopReciveMessage()
    {
        document.removeEventListener('onSMSArrive', this.resolveMessage(this.resolve),false);
    
        window.SMS.stopWatch(function() {
            console.log('Stop Watching');
        }, function() {
            console.log('Not Stop Watching');
        });
    }
    

2. 对于1中的recieveMessage(),需要进行相同的操作。

    public stopReciveMessage()
    {
        document.removeEventListener('onSMSArrive', this.resolveMessage,false);

        window.SMS.stopWatch(function() {
            console.log('Stop Watching');
        }, function() {
            console.log('Not Stop Watching');
        });
    }   

3. 对于1中的recieveMessage(),执行相同操作。

    public stopReciveMessage()
    {
        let self = this;
        this.promise = new Promise((resolve, reject) => {
            document.removeEventListener('onSMSArrive', self.resolveMessage(resolve),false);
            window.SMS.stopWatch(function() {
                console.log('Stop Watching');
            }, function() {
                console.log('Not Stop Watching');
            });
        });
    }

4. 对于1中的recieveMessage()函数,都是相同的。

    public stopReciveMessage()
    {
        let self = this;
        this.promise = (resolve, reject) => {
            document.removeEventListener('onSMSArrive', self.resolveMessage(resolve),false);
            window.SMS.stopWatch(function() {
                console.log('Stop Watching');
            }, function() {
                console.log('Not Stop Watching');
            });
        };
    }

谢谢


你在哪里调用 stopRecieveMessage 方法?尝试在发送消息后立即使用 this.promise.unsubscribe(); - OPV
谢谢评论,我在stopMessageListner()内部调用stopRecieveMessage()函数。不管怎样,当我离开页面时出现了“this.promise.unsubscribe不是一个函数”的错误提示。 - Dilanka Rathnayake
为了移除一个EventListner,你必须传递与"addEventListener"中相同的确切函数,而不是其他拥有相同内容的函数。 - Kaiido
其他可能的目标:https://stackoverflow.com/questions/46704065/removeeventlistener-doesnt-work https://stackoverflow.com/questions/43624322/why-removeeventlistener-is-not-working https://dev59.com/iWkv5IYBdhLWcg3wqSf1 - Kaiido
不确定我如何比所有这些答案更清晰,但是你必须在两个方法中传递完全相同的函数。因此,您必须保留对addEventListener中传递的函数的引用,以便稍后在removeEventListener中传递它。例如,您可以执行 this._listener = this.resolveMessage(resolve); document.addEventListener('onSMSArrive', this._listener); 然后 document.removeEventListener('onSMSArrive', this._listener); - Kaiido
显示剩余2条评论
1个回答

5

我同意在TypeScript中移除事件监听器是非常麻烦的。我已经在Vue中解决了这个问题,像这样:

class App {

    mylistener:EventListener

    created(){
        this.mylistener = (e:Event) => this.logMessage(e,"hello")
        window.addEventListener('click', this.mylistener);
    }

    destroyed(){
        window.removeEventListener("click", this.mylistener)
    }

    logMessage(e:Event, str:String){
        console.log("click event was called")
    }
}

假设当您的组件创建和删除时,会调用“created”和“destroyed”函数。首先检查是否可以使基本示例工作,如果可以,请看看如何应用到您的SMS库中-该库可能有自己的问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接