เปลี่ยนสถานะแบบไดนามิกตามการเชื่อมต่ออินเทอร์เน็ตภายนอก - ตอบสนอง (ออฟไลน์ / ออนไลน์)


10

ฉันมีองค์ประกอบ React ซึ่งรวมถึงสถานะความพร้อมใช้งานของการเชื่อมต่ออินเทอร์เน็ต องค์ประกอบ UI จะต้องเปลี่ยนแปลงแบบไดนามิกตามสถานะเรียลไทม์ ฟังก์ชั่นจะทำงานแตกต่างกันไปตามการเปลี่ยนแปลงของธง

การใช้งานปัจจุบันของฉันสำรวจระยะไกล API โดยใช้ Axios ในทุก ๆ วินาทีโดยใช้ช่วงเวลาและปรับปรุงสถานะให้สอดคล้อง ฉันกำลังมองหาวิธีที่ละเอียดและมีประสิทธิภาพมากขึ้นในการทำงานนี้เพื่อลบข้อผิดพลาด 1 วินาทีของสถานะด้วยต้นทุนการคำนวณขั้นต่ำ ถือว่าออนไลน์ถ้าหากว่าอุปกรณ์นั้นมีการเชื่อมต่ออินเทอร์เน็ตภายนอก

การใช้งานในปัจจุบัน:

class Container extends Component {
  constructor(props) {
    super(props)
    this.state = {
      isOnline: false
    };
    this.webAPI = new WebAPI(); //Axios wrapper
  }

  componentDidMount() {
    setInterval(() => {
      this.webAPI.poll(success => this.setState({ isOnline: success });
    }, 1000);
  }

  render() {
    return <ChildComponent isOnline={this.state.isOnline} />;
  }
}

แก้ไข:

กำลังมองหาโซลูชันที่สามารถตรวจจับการเชื่อมต่ออินเทอร์เน็ตภายนอกได้ อุปกรณ์สามารถเชื่อมต่อกับ LAN ซึ่งไม่มีการเชื่อมต่อภายนอก ดังนั้นจึงถือว่าเป็นแบบออฟไลน์ พิจารณาออนไลน์หากอุปกรณ์นั้นมีการเข้าถึงทรัพยากรอินเทอร์เน็ตภายนอก


2
คุณต้องรู้ว่าคุณออฟไลน์หรือออนไลน์? หรือการเชื่อมต่ออินเทอร์เน็ตอะไร
tudor.gergely

ใช่. โดยทั่วไปทางออนไลน์หรือออฟไลน์
Nilanka Manoj

คุณสามารถแก้ไข API เพื่อให้มีการเชื่อมต่อกับ websocket ได้หรือไม่?
yadejo

คำตอบ:


2

วิธีที่หนึ่ง: การใช้ API เบราว์เซอร์เดิม - Navigator.onLine

ส่งคืนสถานะออนไลน์ของเบราว์เซอร์ คุณสมบัติส่งคืนค่าบูลีนที่มีความหมายจริงแบบออนไลน์และความหมายที่ผิด ๆ แบบออฟไลน์ สถานที่ให้บริการส่งการปรับปรุงเมื่อใดก็ตามที่ความสามารถของเบราว์เซอร์ในการเชื่อมต่อกับการเปลี่ยนแปลงเครือข่าย การปรับปรุงเกิดขึ้นเมื่อผู้ใช้ติดตามลิงก์หรือเมื่อสคริปต์ร้องขอเพจระยะไกล ตัวอย่างเช่นพร็อพเพอร์ตี้ควรส่งคืนค่าเท็จเมื่อผู้ใช้คลิกลิงก์ในไม่ช้าหลังจากที่พวกเขาขาดการเชื่อมต่ออินเทอร์เน็ต

คุณสามารถเพิ่มลงในวงจรชีวิตส่วนประกอบของคุณ:

เล่นด้วยรหัสด้านล่างโดยใช้เครื่องมือพัฒนา Chrome - สลับ "ออนไลน์" เป็น "ออฟไลน์" ใต้แท็บเครือข่าย

class App extends React.PureComponent {
  state = { online: window.navigator.onLine }
  
  componentDidMount() {
    window.addEventListener('offline', this.handleNetworkChange);
    window.addEventListener('online', this.handleNetworkChange);
  }
  
  componentWillUnmount() {
    window.removeEventListener('offline', this.handleNetworkChange);
    window.removeEventListener('online', this.handleNetworkChange);
  }
  
  handleNetworkChange = () => {
    this.setState({ online: window.navigator.onLine });
  }
  
  render() {
    return (
      <div>
       { this.state.online ? 'you\'re online' : 'you\'re offline' }
      </div>
    );
  }
}

ReactDOM.render(
  <App />
, document.querySelector('#app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>


อย่างไรก็ตามฉันคิดว่านี่ไม่ใช่สิ่งที่คุณต้องการคุณต้องการตัวตรวจสอบการเชื่อมต่อแบบเรียลไทม์

วิธีที่สอง: ตรวจสอบการเชื่อมต่ออินเทอร์เน็ตโดยใช้งาน

การยืนยันที่มั่นคงเพียงอย่างเดียวที่คุณจะได้รับหากการเชื่อมต่ออินเทอร์เน็ตภายนอกนั้นใช้งานได้โดยใช้งาน คำถามคือเซิร์ฟเวอร์ที่คุณควรโทรหาเพื่อลดค่าใช้จ่าย?

มีคำตอบมากมายบนอินเทอร์เน็ตสำหรับสิ่งนี้จุดสิ้นสุดใด ๆ ที่ตอบสนองด้วยสถานะ 204 ฉบับย่อนั้นสมบูรณ์แบบเช่น:

  • โทรไปยังเซิร์ฟเวอร์ Google (เพราะเป็นเซิร์ฟเวอร์ที่ผ่านการทดสอบมากที่สุด (?))
  • การเรียกจุดสิ้นสุดสคริปต์ JQuery ที่แคชไว้ (ดังนั้นแม้ว่าเซิร์ฟเวอร์จะไม่ทำงานคุณควรจะสามารถรับสคริปต์ได้ตราบใดที่คุณมีการเชื่อมต่อ)
  • ลองดึงภาพจากเซิร์ฟเวอร์ที่มั่นคง (เช่น: https://ssl.gstatic.com/gb/images/v1_76783e20.png + เวลาประทับวันที่เพื่อป้องกันการแคช)

IMO หากคุณเรียกใช้แอป React นี้บนเซิร์ฟเวอร์การโทรไปยังเซิร์ฟเวอร์ของคุณเองเป็นเรื่องที่สมเหตุสมผลที่สุดคุณสามารถโทรขอให้โหลด/favicon.icoเพื่อตรวจสอบการเชื่อมต่อได้

ความคิด (เรียกเซิร์ฟเวอร์ของคุณเอง) นี้ได้รับการดำเนินการโดยห้องสมุดจำนวนมากเช่นOffline, is-reachableและมีการใช้กันอย่างแพร่หลายทั่วชุมชน คุณสามารถใช้มันหากคุณไม่ต้องการเขียนทุกอย่างด้วยตัวเอง (โดยส่วนตัวแล้วฉันชอบแพคเกจ NPM is-reachableสำหรับความเรียบง่าย)

ตัวอย่าง:

import React from 'react';
import isReachable from 'is-reachable';

const URL = 'google.com:443';
const EVERY_SECOND = 1000;

export default class App extends React.PureComponent {
  _isMounted = true;

  state = { online: false }

  componentDidMount() {
    setInterval(async () => {
      const online = await isReachable(URL);

      if (this._isMounted) {
        this.setState({ online });
      }
    }, EVERY_SECOND);
  }

  componentWillUnmount() {
    this._isMounted = false;
  }

  render() {
    return (
      <div>
       { this.state.online ? 'you\'re online' : 'you\'re offline' }
      </div>
    );
  }
}

แก้ไขการทดสอบการเชื่อมต่อเซิร์ฟเวอร์

ฉันเชื่อว่าสิ่งที่คุณมีอยู่ในปัจจุบันนั้นใช้ได้ดีเพียงตรวจสอบให้แน่ใจว่ามันกำลังเรียกจุดสิ้นสุดที่ถูกต้อง


คำถาม SO ที่คล้ายกัน:


8

คุณสามารถใช้https://developer.mozilla.org/en-US/docs/Web/API/Window/offline_event

window.addEventListener('offline', (event) => {
    console.log("The network connection has been lost.");
});

และhttps://developer.mozilla.org/en-US/docs/Web/API/Window/online_event เพื่อตรวจสอบเมื่อคุณกลับมาออนไลน์

window.addEventListener('online', (event) => {
    console.log("You are now connected to the network.");
});

LAN สามารถถูกตัดการเชื่อมต่อจากภายนอกในสถานการณ์ของฉัน :(
Nilanka Manoj

2

ตั้งค่า hook แบบกำหนดเอง

ติดตั้งตะขอด้วยเหตุการณ์ออนไลน์และออฟไลน์ จากนั้นอัพเดตสถานะและส่งคืน วิธีนี้คุณสามารถใช้งานได้ทุกที่ในแอปด้วยการนำเข้า ตรวจสอบให้แน่ใจว่าคุณทำความสะอาดด้วยฟังก์ชันส่งคืน หากคุณไม่ต้องการคุณจะเพิ่มตัวรับฟังเหตุการณ์เพิ่มมากขึ้นทุกครั้งที่มีส่วนประกอบที่ใช้ตะขอเมาท์

const onlineHook = () => {
  const {isOnline, setOnline} = React.useState();

  React.useEffect(() => {
    const goOnline = function(event){
      setOnline(true);
    });
    const goOffline = function(event){
      setOnline(false);
    });

    window.addEventListener('offline', goOffline);
    window.addEventListener('online', goOnline);

    return () => {
      window.removeEventListener('offline', goOffline);
      window.removeEventListener('online', goOnline);      
    }
  }, [])

  return isOnline
}

หากต้องการใช้สิ่งนี้เพียงนำเข้าเบ็ดด้านบนและเรียกมันว่าสิ่งนี้

const isOnline = onlineHook(); // true if online, false if not

LAN สามารถถูกตัดการเชื่อมต่อจากภายนอกในสถานการณ์ของฉัน :(
Nilanka Manoj

3
หากคุณใช้บริการซ็อกเก็ตเช่น firebase คุณสามารถใช้เหตุการณ์ในตัวที่จับการเชื่อมต่ออินเทอร์เน็ต
Joe Lloyd

คุณสามารถให้โครงกระดูกพื้นฐานของรหัสสำหรับวิธีการที่แนะนำ
Nilanka Manoj

2

คุณสามารถสร้างส่วนประกอบเพื่อใช้ร่วมกันระหว่างคอมโพเนนต์ย่อยทั้งหมด

ใช้:

import React, { useState, useEffect } from "react";

export default function NetworkChecker() {

  const [networkStatus, setNetworkStatus] = useState(true)

  useEffect(() => {
    window.addEventListener('offline', (event) => {
      setNetworkStatus(false)
    });

    window.addEventListener('online', (event) => {
      setNetworkStatus(true)
    });

    return function cleanupListener() {
       window.removeEventListener('online',  setNetworkStatus(true))
       window.removeEventListener('offline', setNetworkStatus(false))
     }

  },[])

  if (networkStatus) {
    return <div className={"alert-success"}>Online</div>
  } else {
    return <div className={"alert-danger"}>Offline</div>
  }

}

คุณลืมที่จะลบฟังเหตุการณ์?
gautamits
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.