@デビッドが述べたように、あなたが本当に働いてインターネットに接続している場合は、あなたを教えてくれます何のシステムイベントはありません。
論理
vm.isInternetUp
ブールを作成し、ユーザが接続されていると仮定する。ユーザーが切断することができます3つの理由があります。
- オフラインイベントは、デバイスが無線LANのチャネルに接続されている場合は何の無線LAN、3Gやイーサネット接続
- がないことを意味し、ブラウザによって発射された場合は、 Wi-Fiチャンネルにインターネットはありません。
- インターネットなしの3G /イーサネット接続もありますが、私たちの場合は関係ありませんでした(この記事には含まれていません)。
ここで、これらの条件のいずれかが発生したときに検出する必要があります。vm.isInternetUp
はfalseになります。そのフラグをオフラインにすると、肯定的な応答が得られるまで、APIへのHTTP要求でループを開始します。
これは非常に面倒ですが、このようにして、インターネット接続のステータスを確認するためにhttpリクエストを継続的に送信することはありません。ユーザーがオンラインに戻ると、1つのhttpだけがサーバーに到達します。
これを実装するさまざまな方法があります
コード(オンライン/オフラインイベントと@ webrusterの回答を見てください)。インターセプタを使用するのは、自分の特定のニーズに最も適しているからです。理由の1のために
vm.isInternetUp = true //assume internet is up at startup
var interceptor = {
request: function(config) {
return vm.checkForInternet(config);
},
responseError: function(reject){
return vm.handleBadWifi(reject)
}
}
は、私たちはWi-Fiに接続しているかどうか、すべての要求でチェックするの角度のhttp request interceptor
を使用しています。そうでなければ、私たちはオフラインであることを意味します。
vm.checkForInternet = function(config) {
if (angular.isUndefined(window.Connection)) {
// The project is run in a web browser so window.Connection doesn’t exist. Assume we have internet.
console.log("window.Connection doesn't exist")
return config;
}
//if there is no internet
if (navigator.connection.type === Connection.NONE || !vm.isInternetUp) {
vm.isInternetUp = false
vm.reconnect();
}
else {
console.log("connected but bad wifi")
}
}
return config;
}
理由2のために、私はすべてのhttp要求を傍受して$ http responseError interceptor
を使用します。ドキュメントに記載されているように、reject.status = -1 usually means the request was aborted
;私たちはインターネット接続がないと結論づけます。
最後に、肯定的な要求を受け取った直後に再接続ループが停止します。 $ httpインターセプタの中にあるので、Angleの$ httpサービスを使うことができないので、かなり長いです。 $ httpを使用すると、循環依存関係が発生します。
vm.reconnect = function() {
//Restart only if we were previously disconnected and after checking that we really have the internet
if (!vm.isInternetUp & !vm.reconnecting) {
console.log("attempting http call")
vm.reconnecting = true;
//backend-host is only pinged if internet was previously disconnected. In this way it does not overload the server.
//we don't use $http because that would induce a circular dependency (we're in an $http interceptor here). As this is a pure js http call this request will not be intercepted.
pureJsHttpGet(backendHost + 'projects/',vm.reconnectSuccess,vm.reconnectError)
}
}
vm.reconnectSuccess = function() {
vm.isInternetUp = true;
vm.reconnecting = false;
}
vm.reconnectError = function (error) {
$timeout(function() {
vm.reconnecting = false;
vm.checkForInternet();
},3000)
console.error("Did not manage to find an internet connection. Retrying in 3 sec", error)
if (navigator.connection.type === Connection.WIFI){
//create a fake reject error so that the wifi errorhandler knows the request failed
var reject = {status:-1}
vm.handleBadWifi(reject)
}
}
function pureJsHttpGet(theUrl, successCallback, errorCallback){
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
successCallback(xmlHttp.responseText);
else if (xmlHttp.readyState == 4 && xmlHttp.status == 0)
errorCallback(xmlHttp)
}
xmlHttp.open("GET", theUrl, true); // true for asynchronous
xmlHttp.send(null);
}
Firebaseを使用していた場合、ユーザーの接続(私が使用していてうまく動作しているようです)を確認するのに非常に便利な方法があります。それとは別にAngularとの接続をチェックすることに関する[this](https://stackoverflow.com/a/16242703/7468384)の質問と回答があります。 –
よく_ _ _ _ _ _接続しているかどうかを知らせるシステムイベントはありません。設定を試す以外には、3000msのタイムアウトが必要です。あなたのサーバ上のいくつかのダミーリソースへのe GETコールを使うことができます。あるいは、あなたがping googleと言ったように - 彼らはあなたのトラフィックを処理できると思います:) – David