BigW Consortium Gitlab

poll.js 3.04 KB
Newer Older
Filipa Lacerda committed
1
import httpStatusCodes from './http_status';
2
import { normalizeHeaders } from './common_utils';
Filipa Lacerda committed
3 4

/**
5
 * Polling utility for handling realtime updates.
6 7 8
 * Requirements: Promise based HTTP client
 *
 * Service for promise based http client and method need to be provided as props
Filipa Lacerda committed
9 10
 *
 * @example
11
 * new Poll({
12 13
 *   resource: resource,
 *   method: 'name',
Filipa Lacerda committed
14
 *   data: {page: 1, scope: 'all'}, // optional
15 16
 *   successCallback: () => {},
 *   errorCallback: () => {},
Filipa Lacerda committed
17
 *   notificationCallback: () => {}, // optional
18 19
 * }).makeRequest();
 *
20 21 22 23 24 25 26 27
 * Usage in pipelines table with visibility lib:
 *
 * const poll = new Poll({
 *  resource: this.service,
 *  method: 'getPipelines',
 *  data: { page: pageNumber, scope },
 *  successCallback: this.successCallback,
 *  errorCallback: this.errorCallback,
Filipa Lacerda committed
28
 *  notificationCallback: this.updateLoading,
29 30 31 32 33
 * });
 *
 * if (!Visibility.hidden()) {
 *  poll.makeRequest();
 *  }
Filipa Lacerda committed
34
 *
35 36 37 38 39 40 41
 * Visibility.change(() => {
 *  if (!Visibility.hidden()) {
 *   poll.restart();
 *  } else {
 *   poll.stop();
 *  }
* });
Filipa Lacerda committed
42 43
 *
 * 1. Checks for response and headers before start polling
Filipa Lacerda committed
44 45
 * 2. Interval is provided by `Poll-Interval` header.
 * 3. If `Poll-Interval` is -1, we stop polling
Filipa Lacerda committed
46 47 48 49
 * 4. If HTTP response is 200, we poll.
 * 5. If HTTP response is different from 200, we stop polling.
 *
 */
Filipa Lacerda committed
50
export default class Poll {
Filipa Lacerda committed
51
  constructor(options = {}) {
52 53
    this.options = options;
    this.options.data = options.data || {};
Filipa Lacerda committed
54 55
    this.options.notificationCallback = options.notificationCallback ||
      function notificationCallback() {};
Filipa Lacerda committed
56 57

    this.intervalHeader = 'POLL-INTERVAL';
Filipa Lacerda committed
58
    this.timeoutID = null;
59
    this.canPoll = true;
Filipa Lacerda committed
60 61 62
  }

  checkConditions(response) {
63
    const headers = normalizeHeaders(response.headers);
64
    const pollInterval = parseInt(headers[this.intervalHeader], 10);
65
    if (pollInterval > 0 && response.status === httpStatusCodes.OK && this.canPoll) {
Filipa Lacerda committed
66 67
      this.timeoutID = setTimeout(() => {
        this.makeRequest();
Filipa Lacerda committed
68 69
      }, pollInterval);
    }
70
    this.options.successCallback(response);
Filipa Lacerda committed
71 72 73
  }

  makeRequest() {
Filipa Lacerda committed
74
    const { resource, method, data, errorCallback, notificationCallback } = this.options;
75 76

    // It's called everytime a new request is made. Useful to update the status.
Filipa Lacerda committed
77
    notificationCallback(true);
78 79

    return resource[method](data)
Filipa Lacerda committed
80 81 82 83 84 85
      .then((response) => {
        this.checkConditions(response);
        notificationCallback(false);
      })
      .catch((error) => {
        notificationCallback(false);
86 87 88
        if (error.status === httpStatusCodes.ABORTED) {
          return;
        }
Filipa Lacerda committed
89 90
        errorCallback(error);
      });
Filipa Lacerda committed
91
  }
92

Filipa Lacerda committed
93 94 95 96 97
  /**
   * Stops the polling recursive chain
   * and guarantees if the timeout is already running it won't make another request by
   * cancelling the previously established timeout.
   */
98 99
  stop() {
    this.canPoll = false;
Filipa Lacerda committed
100
    clearTimeout(this.timeoutID);
101
  }
102 103 104 105

  /**
   * Restarts polling after it has been stoped
   */
106 107 108 109 110 111
  restart(options) {
    // update data
    if (options && options.data) {
      this.options.data = options.data;
    }

112 113 114
    this.canPoll = true;
    this.makeRequest();
  }
Filipa Lacerda committed
115
}