通过FCM在前景中的浏览器中接收一个通知



我正在使用FCM API接收浏览器的推送通知。firebase-messaging-sw.js按预期工作,messaging.setBackgroundMessageHandler仅在Web应用程序在后台时发射一次。但是,当该应用在前景时,我会收到每个浏览器选项卡的一个通知(如果我在3个选项卡中打开该应用程序,则会收到3个通知(。我想知道我应该如何处理这个问题,因为我找不到对此问题的任何参考。这是前景中FCM消息的代码:

import NotificationActionCreators from '../actions/NotificationActionCreators';
import NotificationService from './NotificationService';
import LocalStorageService from './LocalStorageService';
import { FIREBASE_SCRIPT, FCM_URL, FCM_API_KEY, FCM_AUTH_DOMAIN, FCM_PROJECT_ID, FCM_SENDER_ID, PUSH_PUBLIC_KEY } from '../constants/Constants';

class ServiceWorkerService {
constructor() {
    this._messaging = null;
    this._subscriptionData = null;
}
// This function is called once
init() {
    this.loadScript(FIREBASE_SCRIPT, () => this.onFirebaseLoaded());
}
onFirebaseLoaded() {
    // Initialize Firebase
    let config = {
        apiKey: FCM_API_KEY,
        authDomain: FCM_AUTH_DOMAIN,
        projectId: FCM_PROJECT_ID,
        messagingSenderId: FCM_SENDER_ID
    };
    firebase.initializeApp(config);
    this._messaging = firebase.messaging();
    this.requestPermission();
    // Callback fired if Instance ID token is updated.
    this._messaging.onTokenRefresh(() => {
        this._messaging.getToken()
            .then((refreshedToken) => {
                console.log('Token refreshed.');
                NotificationActionCreators.unSubscribe(this._subscriptionData).then(() => {
                    // Indicate that the new Instance ID token has not yet been sent to the
                    // app server.
                    this.setTokenSentToServer(false);
                    // Send Instance ID token to app server.
                    this.sendTokenToServer(refreshedToken);
                }, () => console.log('Error unsubscribing user'));
            })
            .catch(function(err) {
                console.log('Unable to retrieve refreshed token ', err);
            });
    });
    // Handle incoming messages.
    // *** THIS IS FIRED ONCE PER TAB ***
    this._messaging.onMessage(function(payload) {
        console.log("Message received. ", payload);
        const data = payload.data;
        NotificationActionCreators.notify(data);
    });
}
requestPermission() {
    console.log('Requesting permission...');
    return this._messaging.requestPermission()
        .then(() => {
            console.log('Notification permission granted.');
            this.getToken();
        })
        .catch(function(err) {
            console.log('Unable to get permission to notify.', err);
        });
}
getToken() {
    // Get Instance ID token. Initially this makes a network call, once retrieved
    // subsequent calls to getToken will return from cache.
    return this._messaging.getToken()
        .then((currentToken) => {
            if (currentToken) {
                this.sendTokenToServer(currentToken);
            } else {
                // Show permission request.
                console.log('No Instance ID token available. Request permission to generate one.');
                this.setTokenSentToServer(false);
            }
        })
        .catch(function(err) {
            console.log('An error occurred while retrieving token. ', err);
            this.setTokenSentToServer(false);
        });
}
sendTokenToServer(currentToken) {
    const subscriptionData = {
        endpoint: FCM_URL + currentToken,
        platform: 'Web'
    };
    if (!this.isTokenSentToServer()) {
        console.log('Sending token to server...');
        this.updateSubscriptionOnServer(subscriptionData);
    } else {
        console.log('Token already sent to server so won't send it again ' +
            'unless it changes');
    }
    this._subscriptionData = subscriptionData;
}
isTokenSentToServer() {
    return LocalStorageService.get('sentToServer') == 1;
}
setTokenSentToServer(sent) {
    LocalStorageService.set('sentToServer', sent ? 1 : 0);
}
updateSubscriptionOnServer(subscriptionData) {
    if (subscriptionData) {
        NotificationActionCreators.subscribe(subscriptionData);
        this.setTokenSentToServer(true);
        this._subscriptionData = subscriptionData;
    } else {
        console.log('Not subscribed');
    }
}
unSubscribe() {
    this.removeSetTokenSentToServer();
    return this._messaging.getToken()
        .then((currentToken) => {
            return this._messaging.deleteToken(currentToken)
                .then(() => {
                    console.log('Token deleted.');
                    return NotificationActionCreators.unSubscribe(this._subscriptionData);
                })
                .catch(function(err) {
                    console.log('Unable to delete token. ', err);
                    return new Promise(function(resolve, reject) {
                        reject(error)
                    });
                });
       })
        .catch(function(err) {
            console.log('Error retrieving Instance ID token. ', err);
            return new Promise(function(resolve, reject) {
                reject(error)
            });
        });
    }
}
removeSetTokenSentToServer() {
    LocalStorageService.remove('sentToServer');
}
loadScript = function (url, callback) {
    let head = document.getElementsByTagName('head')[0];
    let script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;
    script.onload = callback;
    // Fire the loading
    head.appendChild(script);
}
}

有什么方法可以仅显示第一个选项卡的通知?

我发现实现此目的的唯一方法是检查并设置a "通知ID" 变量在本地存储中使用setTimeout随机时间随机时间:

this._messaging.onMessage(function(payload) {
    const data = payload.data;
    // This prevents to show one notification for each tab
    setTimeout(() => {
        if (localStorage.getItem('lastNotificationId')) != parseInt(data.notId)) {
            localStorage.setItem('lastNotificationId', parseInt(data.notId))
            NotificationActionCreators.notify(data);
        }
    }, Math.random() * 1000);
});

notId是在推送通知中发送的,是通知的标识符。

使用文档。

if (!document.hidden) {
    NotificationActionCreators.notify(data);
}

一种方法是创建每个选项卡的唯一变量,例如Math.random((或(new Date(((。GetMilliseConds((并使用令牌将其存储在服务器上。现在,服务器可以通过将变量连接到消息来定位每个选项卡,每个选项卡都在操作之前检查消息变量。

要减少针对闭合选项卡的几率,请用每个请求发送变量,因此服务器始终针对最新的目标。

相关内容

  • 没有找到相关文章

最新更新