Recently been working with websockets and wanted a way to provide a promise based interface for calls to an api over it mirroring fetch. Inorder to do so I got the api to echo back supplied request ids with the results it handled. But what about if the connection went down? Or for some other unknown reason it was taking far too long to proccess a request? I decided to create a request queue with Promises that would explode rejecting if unresolved for a set time. These promises also need to be resolved externally from requests comming in.
var ExplodingPromise = (timeout, timeoutWith) => {
var result, error
var prom = new Promise((resolve, reject) => {
result = resolve
error = reject
let timer = setTimeout(_ => reject(timeoutWith), timeout)
function destroy() {
clearTimeout(timer)
}
result = (r) => {destroy(); resolve(r)}
error = (r) => {destroy(); reject(r)}
})
prom.result = result
prom.error = error
return prom
}
timeout
Timeout period in millis.timeoutWith
Response if timed out before dealt with.
var promise = ExplodingPromise(5000, 'Timeout')
promise.then(..).catch(..)
// resolve early with
promise.result(..)
// reject early with
promise.error(..)
As you can see, a function returns the actual promise. The timeout
variable specifies the timeout period when it will explode, thereby calling reject if not resolved, or rejected within the time period specified. timeoutWith
is supplied to reject()
if expired.
The promise is returned with result & error functions which can be used to resolve or reject it externally; in my case from an incoming websocket response.
In the development console ([F12] in chrome) copy and paste The Exploding Promise code above then proceed below.
// Set it up to expire in 15 seconds & reject with 'exploded!!' if too late.
var bomb = ExplodingPromise(15000, 'exploded!!')
bomb.then(e=> console.log('Whew!', e)).catch(e => console.error('Oops,', e))
If not responded to in 15 seconds it will call the reject
after 15 secs, and the catch
printing 'Oops, exploded!!'
If before that we type:-
bomb.result('diffused.')
We should get Whew! diffused.
If there was an error somewhere before it times out we could call error
.
var bomb = ExplodingPromise(15000, 'exploded!!')
bomb.then(e=> console.log('Whew!', e)).catch(e => console.error('Oops,', e))
bomb.error('wrong wire!')
This should call the catch and print Oops, wrong wire!
Hopes this helps someone. If there is a better way to do this please feel free to let me know.