您可以使用JavaScript检查您的应用程序是否已连接到互联网吗?
在本文中,我将提供有关此Internet连接检测问题的更新答案。(哇!快说五遍!)
该解决方案将使用JavaScript的Fetch API和带有Async&Await的异步代码。但是首先,让我们看一个公认的解决方案,并讨论为什么它可能不是您的应用程序的最佳选择。
导航器界面的online属性navigator.onLine
经常用于检测浏览器的在线和离线状态。
结合在线和离线事件的侦听器,它似乎为开发人员提供了易于实施的简单解决方案。
首先添加一个加载事件监听器。当load事件触发时,侦听器将检查导航器界面的online属性,然后显示online状态。
导航器的online属性提供布尔(true或false)响应。为了完成侦听器的操作,我们将使用三元语句来设置状态显示值。
window.addEventListener("load", (event) => { const statusDisplay = document.getElementById("status"); statusDisplay.textContent = navigator.onLine ? "Online" : "OFFline";});
那么,为什么导航员这个词呢?好吧,它是对90年代Netscape Navigator浏览器的引用。
将HTML页中的h1元素居中,其ID为“状态”。如果将上面的JavaScript代码应用于页面,则应该看到它显示“在线”。
但这仅在页面加载时更新h1元素。让我们添加脱机和联机事件侦听器,以在任何一个事件触发时更新状态显示。
window.addEventListener("offline", (event) => { const statusDisplay = document.getElementById("status"); statusDisplay.textContent = "OFFline";});window.addEventListener("online", (event) => { const statusDisplay = document.getElementById("status"); statusDisplay.textContent = "Online";});
我们可以转到Chrome Dev Tools的“应用程序”标签,然后单击ServiceWorker来设置浏览器,使其像脱机一样做出响应。
选中并取消选中“脱机”复选框几次。您应该看到状态显示立即响应所触发的脱机和联机事件。
乍一看,以上内容似乎是一个很好的解决方案,非常简单。不幸的是,当我们阅读有关导航器的在线属性以及在线和离线事件的更多信息时,我们发现存在问题。
“在线并不总是意味着连接到互联网。它也可以只意味着连接到某个网络。
嗯,这在工作中有点用力。
因此,如果您确实想确定浏览器的在线状态,则应该开发其他检查方法。
“浏览器以不同的方式实现此属性...您不能假设真实值必然意味着浏览器可以访问互联网。您可能会得到误报……”
这证实了我们对使用navigator的在线属性作为检测Internet连接的解决方案的担忧。该解决方案可能会严重破坏我们的应用程序,而这些应用程序需要了解何时可以使用外部数据源。
一个这样的例子就是当我们试图确定Progressive Web App是否在线时。MDN甚至建议,
“ ...如果您真的想确定浏览器的在线状态,则应开发其他检查方法。”
在网上快速搜索“在线导航器不起作用”时,发现了各种论坛帖子,其中取决于该属性的帖子都遇到了问题。
我们需要知道应用程序何时真正连接到Internet,而不仅仅是路由器或局域网。让我们回到我们的JavaScript文件并重新开始。
这个想法是发出一个请求,并在失败时通过错误捕获来优雅地处理它。如果请求成功,则表明我们在线;如果请求失败,则不是。
我们将每隔一段时间请求一个小图像,以确定在线状态。现代JavaScript通过Async&Await提供了Fetch API和异步代码。我们将使用这些工具来实现我们的目标。
让我们从创建一个名为checkOnlineStatus的异步箭头函数开始。该函数将返回true或false,就像navigator的online属性一样。
在函数内部,我们将设置一个try块,在其中等待一个像素图像的提取请求。确保您的服务人员没有缓存该图像。
200到299之间的HTTP响应代码表示成功,我们将返回状态代码比较的结果。如果响应状态为200到299,则为true,否则为false。
我们还必须提供一个catch块,以在请求失败时捕获错误。如果发生这种情况,我们将在catch块中返回false,以指示我们肯定处于脱机状态。
const checkOnlineStatus = async () => { try { const online = await fetch("/1pixel.png"); return online.status >= 200 && online.status < 300; // either true or false } catch (err) { return false; // definitely offline }};
接下来,我们将使用setInterval方法并将其传递给匿名异步函数。异步函数将等待我们checkOnlineStatus函数的结果。然后,我们将使用三元语句及其结果来显示当前的在线状态。
为了测试此示例,请将间隔延迟设置为每3秒(3000毫秒)。但是,这确实经常发生。每30秒(30000毫秒)检查一次就可以满足您的实际需求。
setInterval(async () => { const result = await checkOnlineStatus(); const statusDisplay = document.getElementById("status"); statusDisplay.textContent = result ? "Online" : "OFFline";}, 3000); // probably too often, try 30000 for every 30 seconds
保存新代码后,让我们重新访问Chrome Dev Tools中的“应用程序”标签以测试离线响应。
我几乎忘记了将加载事件侦听器包含在异步功能中!仅当您具有使用服务工作者提供脱机可用性的Progressive Web App时,负载事件检测才可能很重要。否则,您的网页或应用程序将无法在没有连接的情况下加载。
这是新的加载事件监听器:
window.addEventListener("load", async (event) => { const statusDisplay = document.getElementById("status"); statusDisplay.textContent = (await checkOnlineStatus()) ? "Online" : "OFFline";});
上面的时间间隔代码非常适合在您的应用中显示连接状态。就是说,我不建议依赖在您的应用程序中提出关键数据请求之前20或30秒检查的连接状态。
因此,您应该在请求之前直接调用checkOnlineStatus函数,并在请求数据之前评估响应。
const yourDataRequestFunction = async () => { const online = await checkOnlineStatus(); if (online) { // make data request }}
尽管navigator.onLine得到广泛支持,但在确定我们的应用程序是否真正连接到Internet时,它提供的结果不可靠。利用Fetch API和异步JavaScript,我们可以快速编写更可靠的解决方案。