-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcreateLock.js
77 lines (69 loc) · 1.83 KB
/
createLock.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
'use strict'
const createRawLock = require('./lib/createRawLock.js')
const globalLock = require('./lib/globalLock.js')
function waitForPromise (promise, timeout, unlock) {
if (timeout === undefined) {
return promise.then(function () {
return Promise.resolve(unlock)
})
}
return new Promise(function (resolve, reject) {
promise.then(function () {
clearTimeout(t)
resolve(unlock)
})
let t = setTimeout(function () {
const e = new Error('Timeout[t=' + timeout + ']')
e.code = 'ETIMEOUT'
e.timeout = timeout
reject(e)
}, timeout)
})
}
function wrapProcess (process) {
return function wrapped (unlock) {
return process()
.then(function passResult (result) {
unlock()
return Promise.resolve(result)
})
.catch(function passError (err) {
unlock(err)
return Promise.reject(err)
})
}
}
function createLock (onReleased) {
let currentLock = null
const global = globalLock(function () {
return currentLock === null
})
function lockPromise (timeout) {
const prevLock = currentLock
const thisLock = createRawLock()
currentLock = thisLock
const unlock = function () {
if (currentLock === thisLock) {
currentLock = null
global.trigger()
}
thisLock.unlock(currentLock)
}
if (prevLock !== null) {
return waitForPromise(prevLock, timeout, unlock)
}
global.repeat(onReleased)
return Promise.resolve(unlock)
}
function lock (process, timeout) {
if (typeof process === 'function') {
return lockPromise(timeout).then(wrapProcess(process))
}
timeout = (typeof process === 'number') ? process : timeout
return lockPromise(timeout)
}
lock.released = global.released
return lock
}
createLock.default = createLock
module.exports = createLock