微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何与服务工作者同步我在Apple设备上保存的数据?

如何解决如何与服务工作者同步我在Apple设备上保存的数据?

我知道Apple生态系统不支持Background Sync API,因此您如何解决这个问题,并提出一个可以在Apple生态系统和其他平台上运行的解决方案,现在我有了使用Background Sync的解决方案API,由于某种原因,它实际上不会在IOS上执行任何操作,它只是保存失败的请求,然后再从不同步-s,我可以使用indexedDB包装器以某种方式访问​​同步队列,然后在任意时间进行同步吗? 我试过一次,它破坏了一切,你们有一个主意吗?

    const bgSyncPlugin = new workBox.backgroundSync.Plugin('uploadQueue',{
    maxRetentionTime: 60 * 24 * 60,onSync: async ({ queue }) => {
        return getAccesstoken().then((token) => {
            replayQueue(queue,token).then(() => {
                return showNotification();
            });
        });
    },});

这是我所拥有的代码,所有人。有一个目的,因为我的令牌有超时时间,所以我必须检查令牌是否已过期,然后再继续操作,如果令牌已过期,则替换标头中的令牌,并且我必须在同步时更改数据请求正文,但在苹果设备以外的所有设备上都可以正常工作。 Apple设备从不触发onsync,我尝试通过以下方法监听获取事件并触发onsync:

self.registration.sync.register('uploadQueue');

但是,我没有尝试,我尝试在servvice worker注册注册同步,似乎无济于事。 如果同步注册在iOS上不可行,那么我可以以某种方式访问​​上传队列表吗? PS:我使用dexie.js作为indexedDB包装器,它是带有laravel api的vue.js应用程序,并且同步过程非常复杂,但是它可以正常工作,只需要弄清楚如何在IOS上进行操作即可!

解决方法

在我的脑海里和我的待办事项清单上大约 2 周后,我找到了答案。 现在买些爆米花,把自己绑起来,因为这真是个大块头。 在我的情况下,同步过程非常复杂,因为我的用户可能会离开任何连接很长时间,以至于我的 accessTokens 会过期,所以我也必须检查访问令牌的过期时间并重新获取它。 此外,我的用户可以将新人员添加到人员数据库中,这些人员都有自己唯一的服务器端 ID,因此我必须以先发送人员注册然后发送已完成的任务和活动的方式对我的请求进行排序对于他们,所以我可以从 API 接收相应的 ID。

现在是有趣的部分: 首先你不能使用bgSyncPlugin,因为你不能访问replayQueue,你必须使用一个普通的队列,就像这样:

var bgSyncQueue = new workbox.backgroundSync.Queue('uploadQueue',{
    maxRetentionTime: 60 * 24 * 60,onSync: () => syncData(),});

并将失败的请求推送到获取侦听器内的队列:

this.onfetch = (event) => {
    let requestClone = event.request.clone();
    if (requestClone.method === 'POST' && 'condition to match the requests you need to replay') {
        event.respondWith(
            (() => {
                const promiseChain = fetch(requestClone).catch(() => {
                    return bgSyncQueue.pushRequest(event);
                });
                event.waitUntil(promiseChain);
                return promiseChain;
            })()
        );
    } else {
        event.respondWith(fetch(event.request));
    }
};

当用户有连接时,我们触发“syncData()”函数,在 ios 上这有点复杂(稍后会详细介绍),在 android 上它会自动发生,因为 service worker 看到它有连接,现在让我们检查一下了解 syncData 的作用:

async function syncData() {
    if (bgSyncQueue) //is there data to sync?
        return getAccessToken() //then get the access token,if expired refresh it
            .then((token) => replayQueue(bgSyncQueue,token).then(() => showNotification({ body: 'Succsesful sync',title: 'Data synced to server' })))
            .catch(() => showNotification({ title: 'Sync unsuccessful',body: 'Please find and area with better coverage' })); //replay the requests and show a notification
    return Promise.resolve('empty');//if no requests to replay return with empty
}

对于我们完成的 android/桌面方面的事情,您可以对同步修改的数据感到满意,现在在 iOS 上,我们不能只在用户重新启动 PWA 时才上传用户数据,那是糟糕的用户体验,但是我们正在使用 javascript,一切皆有可能。

有一个消息事件可以在每次客户端代码看到它有互联网时触发,如下所示:

if (this.$online && this.isIOSDevice) {
                    if (window.MessageChannel) {
                        var messageChannel = new MessageChannel();
                        messageChannel.port1.onmessage = (event) => {
                            this.onMessageSuccess(event);
                        };
                    } else {
                        navigator.serviceWorker.onmessage = (event) => {
                            this.onMessageSuccess(event);
                        };
                    }
                    navigator.serviceWorker.ready.then((reg) => {
                        try {
                            reg.active.postMessage(
                                {
                                    text: 'sync',port: messageChannel && messageChannel.port2,},[messageChannel && messageChannel.port2]
                            );
                        } catch (e) {
                            //firefox support
                            reg.active.postMessage({
                                text: 'sync',});
                        }
                    });
                }

这是在 Vue.js watch 函数中,它监视我们是否有连接,如果有连接,它还会检查这是否是来自苹果生态系统的设备,如下所示:

isIosDevice() {
            return !!navigator.platform && /iPad|iPhone|MacIntel|iPod/.test(navigator.platform) && /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
        }

所以它告诉服务工作者它有互联网并且它必须同步,在这种情况下,这段代码被激活:

this.onmessage = (event) => {
    if (event.data.text === 'sync') {
        event.waitUntil(
            syncData().then((res) => {
                if (res !== 'empty') {
                    if (event.source) {
                        event.source.postMessage('doNotification');//this is telling the client code to show a notification (i have a built in notification system into the app,that does not use push notification,just shows a little pill on the bottom of the app with the message)
                    } else if (event.data.port) {
                        event.data.port.postMessage('doNotification'); //same thing
                    }
                    return res;
                }
            })
        );
    }
};

现在我认为最有用的部分是重播队列功能,这家伙从 getAccessToken 获取队列和令牌,然后像发条一样做事:

    const replayQueue = async (queue,token) => {
        let entry;
        while ((entry = await queue.shiftRequest())) {//while we have requests to replay
            let data = await entry.request.clone().json();
            try {
//replay the person registrations first and store them into indexed db
                if (isPersonRequest) {
                    //if new person
                    await fetchPerson(entry,data,token);
//then replay the campaign and task submissions
                } else if (isTaskOrCampaignRequest) {
                    //if task
                    await fetchCampaigns(entry,token);
                } 
            } catch (error) {
                showNotification({ title: 'no success',body: 'go for better internet plox' });
                await queue.unshiftRequest(entry); //put failed request back into queue,and try again later
            }
        }
        return Promise.resolve();
    };

现在这是如何在 iOS 设备上使用这个家伙并让 Apple 疯狂的大局:) 我对任何相关问题持开放态度,在这段时间里,我认为我已经非常擅长与 Service Worker 相关因为这不是这个项目唯一困难的部分,但我离题了,这是另一天的故事。

(你可能会看到错误处理并不完美,也许这个东西不是最安全的,但是这个项目的用户数量很少,有固定数量的用户知道如何使用它以及它是什么确实如此,所以在这种情况下我并不真的害怕安全,但是如果您在更严肃的项目中使用,您可能希望改进一些东西)

希望我能帮上忙,祝大家度过愉快的一天。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。