Guest User

Untitled

a guest
Jul 18th, 2018
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.13 KB | None | 0 0
  1. import React from "react";
  2. import ReactDOM from "react-dom";
  3.  
  4.  
  5. class OnlineStatusEventDispatcher {
  6. constructor() {
  7. this.timer;
  8. this.initialStatus;
  9. this.wasOnlineLastTime;
  10.  
  11. this.isDispatcherCalledForFirstTime = true;
  12.  
  13. this.setupFetchConf = this.setupFetchConf.bind(this);
  14. this.checkOnlineStatus = this.checkOnlineStatus.bind(this);
  15. this.handleDispatching = this.handleDispatching.bind(this);
  16. this.initDispatcher = this.initDispatcher.bind(this);
  17. this.cancelDispatcher = this.cancelDispatcher.bind(this);
  18. this.setInitialStatus = this.setInitialStatus.bind(this);
  19. this.setConf = this.setConf.bind(this);
  20.  
  21. this.onLineEvent = new CustomEvent('isOnlineFallback', {
  22. detail: {
  23. onLine: true
  24. }
  25. });
  26.  
  27. this.offLineEvent = new CustomEvent('isOnlineFallback', {
  28. detail: {
  29. onLine: false
  30. }
  31. });
  32.  
  33. this.setupFetchConf();
  34. }
  35.  
  36. setConf(conf) {
  37. this.conf = conf;
  38. }
  39.  
  40. setInitialStatus(status) {
  41. this.initialStatus = status;
  42. }
  43.  
  44. setupFetchConf() {
  45. const headers = new Headers();
  46. headers.append('pragma', 'no-cache');
  47. headers.append('cache-control', 'no-cache');
  48.  
  49. this.fetchConf = {
  50. method: 'GET',
  51. headers: headers,
  52. };
  53. }
  54.  
  55. async checkOnlineStatus(path = '') {
  56. const timeout = new Promise((resolve, reject) => {
  57. setTimeout(reject, this.conf.timeoutInterval ? this.conf.timeoutInterval : 3000);
  58. });
  59. let isOnline = true;
  60.  
  61. await Promise.race([
  62. fetch(`/${path}`, this.fetchConf),
  63. timeout
  64. ])
  65. .then(() => (isOnline = true))
  66. .catch(() => (isOnline = false));
  67.  
  68. return isOnline;
  69. }
  70.  
  71. async handleDispatching() {
  72. const isOnline = await this.checkOnlineStatus(this.conf.serverResourcePath);
  73.  
  74. if (this.isDispatcherCalledForFirstTime && this.initialStatus === isOnline) {
  75. this.isDispatcherCalledForFirstTime = false;
  76. if (this.initialStatus) {
  77. this.wasOnlineLastTime = true;
  78. }
  79. return;
  80. }
  81.  
  82. if (isOnline && !this.wasOnlineLastTime) {
  83. window.dispatchEvent(this.onLineEvent);
  84. this.wasOnlineLastTime = true;
  85. } else if (!isOnline && this.wasOnlineLastTime) {
  86. window.dispatchEvent(this.offLineEvent);
  87. this.wasOnlineLastTime = false;
  88. }
  89. }
  90.  
  91. initDispatcher(interval = 6000) {
  92. this.timer = window.setInterval(this.handleDispatching, interval);
  93. }
  94.  
  95. cancelDispatcher() {
  96. this.timer.clearInterval();
  97. }
  98. }
  99.  
  100. //singleton
  101. const dispatcherInstance = new OnlineStatusEventDispatcher();
  102.  
  103.  
  104. const withNetworkInfo = (conf) => (Component) => {
  105. return class extends React.Component {
  106. constructor() {
  107. super();
  108.  
  109. this.state = {
  110. isConnectionSupported: false,
  111. isOnline: true,
  112. networkInfo: null,
  113. }
  114.  
  115. this._validateConf(conf);
  116.  
  117. if (conf.enableCustomOnlineStatusChecking) {
  118. this.onlineStatusEventDispatcher = dispatcherInstance;
  119. this.onlineStatusEventDispatcher.setConf(conf);
  120. }
  121. }
  122.  
  123. componentWillMount() {
  124. if (conf.enableCustomOnlineStatusChecking) {
  125. this._setInitialOnlineStatus()
  126. .then(status => {
  127. this.setState({
  128. isOnline: status
  129. });
  130.  
  131. this.onlineStatusEventDispatcher.setInitialStatus(status);
  132. this.onlineStatusEventDispatcher.initDispatcher(conf.offlineRequestsInterval);
  133. });
  134. } else {
  135. this.setState({
  136. isOnline: navigator.onLine
  137. });
  138. }
  139.  
  140. if ('connection' in navigator) {
  141. this.setState({
  142. isConnectionSupported: true,
  143. networkInfo: navigator.connection
  144. });
  145. }
  146. }
  147.  
  148. componentDidMount() {
  149. if (conf.enableCustomOnlineStatusChecking) {
  150. window.addEventListener('isOnlineFallback', this._onlineStatusFallbackChange.bind(this));
  151. } else {
  152. window.addEventListener('online', this._onOnlineStatusChange.bind(this));
  153. window.addEventListener('offline', this._onOnlineStatusChange.bind(this));
  154. }
  155.  
  156. this.state.isConnectionSupported && navigator.connection.addEventListener('change', this._onConnectionChange.bind(this));
  157. }
  158.  
  159. componentWillUnmount() {
  160. if (conf.enableCustomOnlineStatusChecking) {
  161. window.removeEventListener('isOnlineFallback', this._onlineStatusFallbackChange.bind(this));
  162. this.onlineStatusEventDispatcher.cancelDispatcher();
  163. } else {
  164. window.removeEventListener('online', this._onOnlineStatusChange.bind(this));
  165. window.removeEventListener('offline', this._onOnlineStatusChange.bind(this));
  166. }
  167.  
  168. this.state.isConnectionSupported && navigator.connection.removeEventListener('change', this._onConnectionChange.bind(this));
  169. }
  170.  
  171. _validateConf(conf) {
  172. if (conf.timeoutInterval >= conf.offlineRequestsInterval) {
  173. throw Error('timeoutInteval param must not exceed offlineRequestInterval param value.');
  174. }
  175. }
  176.  
  177. async _setInitialOnlineStatus() {
  178. const isOnline = await this.onlineStatusEventDispatcher.checkOnlineStatus();
  179.  
  180. return isOnline;
  181. }
  182.  
  183. _onOnlineStatusChange() {
  184. this.setState({
  185. isOnline: navigator.onLine
  186. });
  187. }
  188.  
  189. _onlineStatusFallbackChange(event) {
  190. console.log('EVENT', event.detail);
  191. this.setState({
  192. isOnline: event.detail.onLine
  193. })
  194. }
  195.  
  196. _onConnectionChange() {
  197. this.setState({
  198. networkInfo: navigator.connection
  199. });
  200. }
  201.  
  202. render() {
  203. return (
  204. <Component
  205. networkInfo={this.state.networkInfo}
  206. isOnline={this.state.isOnline}
  207. {...this.props} />
  208. );
  209. }
  210. }
  211. }
  212.  
  213. class InfoLogger extends React.Component {
  214. constructor() {
  215. super();
  216. }
  217.  
  218. render() {
  219. return (
  220. <span>{this.props.networkInfo.effectiveType} / {this.props.isOnline ? 'online' : 'offline'}</span>
  221. );
  222. }
  223. }
  224.  
  225. const InfoLoggerExample = withNetworkInfo({
  226. enableCustomOnlineStatusChecking: true,
  227. serverResourcePath: 'favicon.ico',
  228. offlineRequestsInterval: 5000,
  229. timeoutInterval: 3000
  230. })(InfoLogger);
  231.  
  232. class Application extends React.Component {
  233. render() {
  234. return <div>
  235. <h1>{<InfoLoggerExample />}</h1>
  236. </div>;
  237. }
  238. }
  239.  
  240. ReactDOM.render(<Application />, document.getElementById('app'));
Add Comment
Please, Sign In to add comment