Completed
Push — dev ( d2c354...4dcac8 )
by Fike
28s
created

timeout.js ➔ ... ➔ target.cancel   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
var Future = require('./Future').Future
2
3
/**
4
 * @class
5
 * @param {string} message
6
 */
7
function TimeoutException (message) {
8
  this.message = message || 'Timeout has exceeded'
9
  this.stack = (new Error()).stack
10
}
11
12
var _ = TimeoutException
13
14
_.prototype = Object.create(Error.prototype)
15
_.prototype.name = 'TimeoutException'
16
_.prototype.constructor = _
17
18
function CancellationException (message) {
19
  this.message = message || 'Promise has been cancelled'
20
  this.stack = (new Error()).stack
21
}
22
23
_ = CancellationException
24
_.prototype = Object.create(Error.prototype)
25
_.prototype.name = 'CancellationException'
26
_.prototype.constructor = _
27
28
/**
29
 * @interface ICancellablePromise
30
 * @template T
31
 * @extends Thenable.<T>
32
 */
33
34
/**
35
 * @function ICancellablePromise#cancel
36
 *
37
 * @param {boolean} [silent] Whether to cancel with CancellationException or
38
 * just pretend that nothing has happened
39
 *
40
 * @return ICancellablePromise The very same instance
41
 */
42
43
/**
44
 * @param {Promise.<*>|Thenable.<*>} promise Promise to add time bound to
45
 * @param {int} [timeout] Timeout in milliseconds
46
 * @param {string} [message]
47
 * @return {ICancellablePromise.<*>}
48
 */
49
function timeout (promise, timeout, message) {
50
  if (typeof timeout !== 'number' || timeout < 0) {
51
    promise.cancel = function () { return promise }
52
    return promise
53
  }
54
  var wrapper = Future.wrap(promise)
55
  var bind = setTimeout(function () {
56
    message = message || 'Timeout of ' + timeout + ' ms has exceeded'
57
    wrapper.reject(new TimeoutException(message))
58
  }, timeout)
59
  var cancel = function (silent) {
60
    clearTimeout(bind)
61
    if (!silent) {
62
      wrapper.reject(new CancellationException())
63
    }
64
  }
65
  wrapper.then(cancel, cancel)
66
  wrapper.cancel = function (silent) {
67
    cancel(silent)
68
    return wrapper
69
  }
70
  return wrapper
71
}
72
73
/**
74
 * Delays processing of callback for specified time. If no callback is
75
 * given, returns empty promise that will resolve in specified time
76
 *
77
 * @param {int} time
78
 * @param {Function} [callback]
79
 *
80
 * @return {Thenable.<*>}
81
 */
82
function delay (time, callback) {
83
  callback = callback || function () {}
84
  var target = new Future()
85
  var resolve = function () {
86
    try {
87
      target.resolve(callback())
88
    } catch (e) {
89
      target.reject(e)
90
    }
91
  }
92
  var bind = setTimeout(resolve, time)
93
  target.cancel = function (silent) {
94
    clearTimeout(bind)
95
    silent ? resolve() : target.reject(new CancellationException())
96
    return target
97
  }
98
  return target
99
}
100
101
/**
102
 * Wraps given promise with another one which won't resolve earlier
103
 * than specified time.
104
 *
105
 * @param {Thenable.<*>} promise
106
 * @param {int} time Throttle time in milliseconds
107
 * @return {Thenable.<*>}
108
 */
109
function throttle (promise, time) {
110
  var delayed = delay(time)
111
  var target = delayed
112
    .then(function () {
113
      return promise
114
    })
115
  target.cancel = function (silent) {
116
    delayed.cancel(silent)
117
    return target
118
  }
119
  return target
120
}
121
122
module.exports = {
123
  timeout: timeout,
124
  delay: delay,
125
  throttle: throttle,
126
  TimeoutException: TimeoutException,
127
  CancellationException: CancellationException
128
}
129