录像与后台不同步_与服务人员的后台同步

录像与后台不同步

Service workers have been having a moment. In March 2018, iOS Safari began including service workers -- so all major browsers at this point support offline options. And this is more important than ever -- 20% of adults in the United States are without Internet at home, leaving these individuals relying solely on a cellphone to access most information. This can include something as simple as checking a bank balance or something as tedious as searching for a job, or even researching illnesses.

服务人员一直在片刻。 在2018年3月,iOS Safari开始包括服务人员-因此目前所有主要的浏览器都支持离线选项。 这比以往任何时候都更加重要-美国20%的成年人在家中没有互联网,使这些人仅依靠手机访问大多数信息。 这可能包括检查银行存款余额之类的简单操作,或者寻找工作甚至研究疾病之类的乏味操作。

Offline-supported applications are a necessity, and including a service worker is a great start. However, service workers alone will only get someone part of the way to a truly seamless online-to-offline experience. Caching assets is great, but without an internet connection you still can't access new data or send any requests.

脱机支持的应用程序是必须的,并且包括服务工作者是一个很好的开始。 但是,仅服务人员就只能让某人参与到真正无缝的在线到离线体验中。 缓存资产非常棒,但是如果没有Internet连接,您仍然无法访问新数据或发送任何请求。

请求生命周期 (The Request Lifecycle)

Currently a request might look like this:

目前,请求可能如下所示:

The Request Lifecycle

A user pushes a button and a request is fired off to a server somewhere. If there is internet, everything should go off without a hitch. If there is not internet ... well things aren't so simple. The request won't be sent, and perhaps the user realizes their request never made it through, or perhaps they are unaware. Fortunately, there's a better way.

用户按下按钮,请求就被发送到某处的服务器。 如果有互联网,一切应该顺利进行。 如果没有互联网...那么事情就不是那么简单。 该请求将不会发送,也许用户意识到他们的请求从未通过,或者他们没有意识到。 幸运的是,有更好的方法。

Enter: background sync.

输入: 后台同步

后台同步 (Background Sync)

The Background Sync Lifecycle

The lifecycle with background sync is slightly different. First a user makes a request, but instead of the request being attempted immediately, the service worker steps in. The service worker will check if the user has internet access -- if they do, great. The request will be sent. If not, the service worker will wait until the user does have internet and at that point send the request, after it fetches data out of IndexedDB. Best of all, background sync will go ahead and send the request even if the user has navigated away from the original page.

具有后台同步的生命周期略有不同。 首先,用户发出请求,但服务工作者介入,而不是立即尝试请求。服务工作者将检查用户是否可以访问Internet-如果可以,则很好。 该请求将被发送。 如果没有,则服务工作者将等到用户确实具有互联网并在请求从IndexedDB中获取数据之后发送请求。 最重要的是,即使用户已离开原始页面,后台同步也将继续发送请求。

Background Sync Support

While background sync is fully supported only in Chrome, Firefox and Edge are currently working on implementing it. Fortunately with the use of feature detection and onLine and offLine events, we can safely use background sync in any application while also including a fallback.

虽然仅在Chrome中完全支持后台同步,但是Firefox和Edge目前正在实现它。 幸运的是,通过使用功能检测以及onLineoffLine事件 ,我们可以在任何应用程序中安全地使用后台同步,同时还包括回退功能。

A simple newsletter signup app

(If you'd like to follow along with the demo, the code can be found here and the demo itself is found here.)

(如果您想跟着演示一起进行, 可以在这里找到代码,并在这里找到 演示本身。 )

Let's assume we have a very simple newsletter signup form. We want the user to be able to signup for our newsletter whether or not they currently have internet access. Let's start with implementing background sync.

假设我们有一个非常简单的新闻简报注册表单。 我们希望用户能够注册我们的时事通讯,无论他们当前是否可以访问互联网。 让我们从实现后台同步开始。

(This tutorial assumes you are familiar with service workers. If you are not, this is a good place to start. If you're unfamiliar with IndexedDB, I recommend starting here.)

(本教程假定您熟悉服务人员。如果不熟悉, 这是一个不错的起点。如果您不熟悉IndexedDB, 建议从这里开始。 )

When you are first setting up a service worker, you'll have to register it from your application's JavaScript file. That might look like this:

首次设置服务工作者时,您必须从应用程序JavaScript文件中进行注册。 可能看起来像这样:

if(navigator.serviceWorker) {
      navigator.serviceWorker.register('serviceworker.js');
}

Notice that we are using feature detection even when registering the service worker. There's almost no downside to using feature detection and it'll stop errors from cropping up in older browsers like Internet Explorer 11 when the service worker isn't available. Overall, it's a good habit to keep up even if it isn't always necessary.

请注意,即使在注册服务人员时,我们也在使用功能检测。 使用功能检测几乎没有任何弊端,并且当服务工作者不可用时,它可以防止错误在较旧的浏览器(例如Internet Explorer 11)中出现。 总体而言,这是一个良好的习惯,即使并非总是必要,也要跟上。

When we set up background sync, our register function changes and may look something like this:

当我们设置后台同步时,我们的注册功能会发生变化,可能看起来像这样:

if(navigator.serviceWorker) {
        navigator.serviceWorker.register('./serviceworker.js')
        .then(function() {
            return navigator.serviceWorker.ready
        })
        .then(function(registration) {
            document.getElementById('submitForm').addEventListener('click', (event) => {
                registration.sync.register('example-sync')
                .catch(function(err) {
                    return err;
                })
            })
        })
        .catch( /.../ )
    }

This is a lot more code, but we'll break it down one line at a time.

这是很多代码,但是我们一次将其分解为一行。

First we are registering the service worker like before, but now we're taking advantage of the fact that the register function returns a promise. The next piece you see is navigator.serviceWorker.ready. This is a read-only property of a service worker that essentially just lets you know if the service worker is ready or not. This property provides a way for us to delay execution of the following functions until the service worker is actually ready.

首先,我们像以前一样注册服务工作者,但现在我们利用了register函数返回promise的事实。 您看到的下一块是navigator.serviceWorker.ready 。 这是服务人员的只读属性,实际上只是让您知道服务人员是否准备就绪。 此属性为我们提供了一种方法,可以延迟以下功能的执行,直到服务工作者实际准备就绪为止。

Next we have a reference to the service worker's registration. We'll put an event listener on our submit button, and at that point register a sync event and pass in a string. That string will be used over on the service worker side later on.

接下来,我们将参考服务人员的注册。 我们将事件监听器放在“提交”按钮上,然后注册一个同步事件并传递一个字符串。 稍后将在服务工作者端使用该字符串。

Let's re-write this real quick to include feature detection, since we know background sync doesn't yet have wide support.

让我们重新编写一下包含功能检测的功能,因为我们知道后台同步还没有广泛的支持。

if(navigator.serviceWorker) {
        navigator.serviceWorker.register('./serviceworker.js')
        .then(function() {
            return navigator.serviceWorker.ready
        })
        .then(function(registration) {
            document.getElementById('submitForm').addEventListener('click', (event) => {
                if(registration.sync) {
                    registration.sync.register('example-sync')
                    .catch(function(err) {
                        return err;
                    })
                }
            })
        })
    }

Now let's take a look at the service worker side.

现在,让我们看一下服务人员端。

self.onsync = function(event) {
    if(event.tag == 'example-sync') {
        event.waitUntil(sendToServer());
    }
}

We attach a function to onsync, the event listener for background sync. We want to watch for the string we passed into the register function back in the application's JavaScript. We're watching for that string using event.tag.

我们在onsync附加了一个函数,用于后台同步的事件监听器。 我们想查看返回到应用程序JavaScript中的注册函数的字符串。 我们正在使用event.tag监视该字符串。

We're also using event.waitUntil. Because a service worker isn't continually running -- it "wakes up" to do a task and then "goes back to sleep" -- we want to use event.waitUntil to keep the service worker active. This function accepts a function parameter. The function we pass in will return a promise, and event.waitUntil will keep the service worker "awake" until that function resolves. If we didn't use event.waitUntil the request might never make it to the server because the service worker would run the onsync function and then immediately go back to sleep.

我们还使用event.waitUntil 。 因为服务人员不是一直在运行-它“醒来”执行任务,然后“回到睡眠状态”-我们想要使用event.waitUntil来保持服务人员处于活动状态。 该函数接受函数参数。 我们传入的函数将返回一个promise, event.waitUntil将使服务工作者保持“清醒”状态,直到该函数解决为止。 如果我们不使用event.waitUntil该请求可能永远不会到达服务器,因为服务工作者将运行onsync函数,然后立即返回睡眠状态。

Looking at the code above, you'll notice we don't have to do anything to check on the status of the user's internet connection or send the request again if the first attempt fails. Background sync is handling all of that for us. Let's take a look at how we access the data in the service worker.

查看上面的代码,您会发现我们无需执行任何操作即可检查用户的Internet连接状态,或者在首次尝试失败时再次发送请求。 后台同步正在为我们处理所有这些。 让我们看一下我们如何访问服务工作者中的数据。

Because a service worker is isolated in its own worker, we won't be able to access any data directly from the DOM. We'll rely on IndexedDB to get the data and then send the data onward to the server.

由于服务工作者独立于其自己的工作者,因此我们将无法直接从DOM访问任何数据。 我们将依靠IndexedDB来获取数据,然后将数据继续发送到服务器。

IndexedDB utilizes callbacks while a service worker is promise-based, so we'll have to account for that in our function. (There are wrappers around IndexedDB that make this process a little simpler. I recommend checking out IDB or money-clip.)

当服务工作者基于承诺时,IndexedDB使用回调,因此我们必须在函数中考虑这一点。 (IndexedDB周围有包装器,使此过程更简单。我建议您查看IDBmoney-clip 。)

Here is what our function might look like:

这是我们的函数可能的样子:

return new Promise(function(resolve, reject) {
    var db = indexedDB.open('newsletterSignup');
    db.onsuccess = function(event) {
        this.result.transaction("newsletterObjStore").objectStore("newsletterObjStore").getAll().onsuccess = function(event) {
            resolve(event.target.result);
        }
    }
    db.onerror = function(err) {
        reject(err);
    }
});

Walking through it, we're returning a promise, and we'll use the resolve and reject parameters to make this function more promise-based to keep everything in line with the service worker.

通过它,我们将返回一个Promise,并且我们将使用resolvereject参数使此函数更加基于Promise,以使一切与Service Worker保持一致。

We'll open a database and we'll use the getAll method to pull all the data from the specified object store. Once that is success, we'll resolve the function with the data. If we have an error, we'll reject. This keeps our error handling working the same way as all of the other promises and makes sure we have the data before we send it off to the server.

我们将打开一个数据库,并使用getAll方法从指定的对象存储中提取所有数据。 一旦成功,我们将使用数据解析功能。 如果有错误,我们将拒绝。 这样可以使我们的错误处理与所有其他promise的工作方式相同,并确保在将数据发送到服务器之前我们已经有了数据。

After we get the data, we just make a fetch request the way we normally would.

在获取数据之后,我们将以通常的方式发出获取请求。

fetch('https://www.mocky.io/v2/5c0452da3300005100d01d1f', {
    method: 'POST',
    body: JSON.stringify(response),
    headers:{
        'Content-Type': 'application/json'
    }
})

Of course all of this will only run if the user has Internet access. If the user does not have Internet access, the service worker will wait until the connection has returned. If, once the connection returns, the fetch request fails, the service worker will attempt a maximum of three times before it stops trying to send the request for good.

当然,只有在用户可以访问Internet的情况下,所有这些操作才会运行。 如果用户无法访问Internet,则服务工作者将等待直到连接恢复。 如果一旦连接返回,获取请求失败,则服务工作者将尝试最多进行三次,然后再停止尝试发送请求。

Now that we've set up background sync, we are ready to set up our fallback for browsers that don't support background sync.

既然我们已经设置了后台同步,我们就可以为不支持后台同步的浏览器设置后备。

支持旧版浏览器 (Support for legacy browsers)

Unfortunately, service workers aren't supported in legacy browsers and the background sync feature is only supported in Chrome as of now. In this post we'll focus on utilizing other offline features in order to mimic background sync and offer a similar experience.

遗憾的是,旧版浏览器不支持服务人员,并且到目前为止,Chrome仅支持后台同步功能。 在本文中,我们将重点介绍利用其他脱机功能来模拟背景同步并提供类似的体验。

线上和线下活动 (Online and Offline Events)

We'll start with online and offline events. Our code to register the service work last time looked like this:

我们将从在线和离线事件开始。 我们上次注册服务工作的代码如下所示:

if(navigator.serviceWorker) {
    navigator.serviceWorker.register('./serviceworker.js')
    .then(function() {
        return navigator.serviceWorker.ready
    })
    .then(function(registration) {
        document.getElementById('submitForm').addEventListener('click', (event) => {
            event.preventDefault();
            saveData().then(function() {
                if(registration.sync) {
                    registration.sync.register('example-sync')
                    .catch(function(err) {
                        return err;
                    })
                }
            });
        })
    })
}

Let's do a quick recap of this code. After we register the service worker, we use the promise returned from navigator.serviceWorker.ready to ensure that the service worker is in fact ready to go. Once the service worker is ready to go, we'll attach an event listener to the submit button and immediately save the data into IndexedDB. Lucky for us IndexedDB is supported in effectively all browsers, so we can pretty well rely on it.

让我们快速回顾一下这段代码。 在注册服务工作者之后,我们使用从navigator.serviceWorker.ready返回的承诺来确保服务工作者实际上已经准备就绪。 一旦服务工作者准备就绪,我们将在事件提交器上附加一个事件侦听器,然后立即将数据保存到IndexedDB中。 对我们来说幸运的是,所有浏览器均有效地支持IndexedDB,因此我们可以很好地依靠它。

After we've saved the data, we use feature detection to make sure we can use background sync. Let's go ahead and add our fallback plan in the else.

保存数据后,我们使用功能检测来确保可以使用后台同步。 让我们继续,在其他情况下添加我们的后备计划。

if(registration.sync) {
    registration.sync.register('example-sync')
    .catch(function(err) {
        return err;
    })
} else {
    if(navigator.onLine) {
        sendData();
    } else {
        alert("You are offline! When your internet returns, we'll finish up your request.");
    }
}

额外的支持 (Additional support)

We're using navigator.onLine to check the user's internet connection. If they have a connection, this will return true. If they have an internet connection, we'll go ahead and send off the data. Otherwise, we'll pop up an alert letting the user know that their data hasn't been sent.

我们正在使用navigator.onLine来检查用户的互联网连接。 如果他们有连接,则返回true。 如果他们有互联网连接,我们将继续发送数据。 否则,我们将弹出一个警报,让用户知道其数据尚未发送。

Let's add a couple of events to watch the internet connection. First we'll add an event to watch the connection going offline.

让我们添加一些事件来观看Internet连接。 首先,我们将添加一个事件以观看连接离线。

window.addEventListener('offline', function() {
    alert('You have lost internet access!');
});

If the user loses their internet connection, they'll see an alert. Next we'll add an event listener for watching for the user to come back online.

如果用户失去互联网连接,他们会看到警报。 接下来,我们将添加一个事件侦听器,以监视用户重新联机。

window.addEventListener('online', function() {
    if(!navigator.serviceWorker && !window.SyncManager) {
        fetchData().then(function(response) {
            if(response.length > 0) {
                return sendData();
            }
        });
    }
});

Once the user's internet connection returns, we'll do a quick check if a service worker is available and also sync being available. We want to check on this because if the browser has sync available, we don't need to rely on our fallback because it would result in two fetches. However, if we do use our fallback, we first pull the data out of IndexedDB like so:

用户的互联网连接恢复后,我们将快速检查服务工作者是否可用以及同步是否可用。 我们要检查这一点,因为如果浏览器具有可用的同步功能,我们就不必依赖备用,因为它将导致两次提取。 但是,如果确实使用后备,则首先要像这样将数据从IndexedDB中拉出:

var myDB = window.indexedDB.open('newsletterSignup');

myDB.onsuccess = function(event) {
    this.result.transaction("newsletterObjStore").objectStore("newsletterObjStore").getAll().onsuccess = function(event) {
        return event.target.result;
    };
};

myDB.onerror = function(err) {
    reject(err);
}

Next we'll verify that the response from IndexedDB actually has data, and if it does we'll send it to our server.

接下来,我们将验证IndexedDB的响应是否确实包含数据,如果有,我们会将其发送到我们的服务器。

This fallback won't entirely replace background sync for a few reasons. Firstly, we are checking for online and offline events, which we do not need to do with background sync because background sync handles all that for us. Additionally, background sync will continue attempting to send requests even if the user has navigated away from the page.

由于一些原因,这种后备功能不会完全取代后台同步。 首先,我们要检查在线和离线事件,我们不需要后台同步,因为后台同步可以为我们处理所有事情。 此外,即使用户已经离开页面,后台同步也将继续尝试发送请求。

Our solution won't be able to send the request even if the user navigates away, but we can pre-emptively check IndexedDB as soon as the page loads and send any cached data immediately. This solution also watches for any network connection changes, and sends cached data as soon as the connection returns.

即使用户离开,我们的解决方案也无法发送请求,但是我们可以在页面加载后立即抢先检查IndexedDB并立即发送所有缓存的数据。 该解决方案还监视任何网络连接更改,并在连接返回后立即发送缓存的数据。

离线支持的下一步 (Next steps in offline support)

Edge and Firefox browsers are currently working on implementing background sync, which is fantastic. It is one of the best features for providing a more empathetic experience for users moving between internet connection and connection loss. Fortunately with a little help from online and offline events and IndexedDB, we can start providing a better experience for users today.

Edge和Firefox浏览器当前正在实现后台同步,这太棒了。 它是为在Internet连接和连接丢失之间移动的用户提供更多移情体验的最佳功能之一。 幸运的是,在联机和脱机事件以及IndexedDB的帮助下,我们可以开始为当今的用户提供更好的体验。

If you'd like to learn more about offline techniques, check out my blog: carmalou.com or follow me on Twitter.

如果您想了解有关离线技术的更多信息,请访问我的博客: carmalou.com在Twitter上关注我。

翻译自: https://davidwalsh.name/background-sync

录像与后台不同步

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值