Skip to content

Instantly share code, notes, and snippets.

@neutralvibes
Last active July 13, 2021 15:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save neutralvibes/aca3f94da270f04a3cb30b7514123b53 to your computer and use it in GitHub Desktop.
Save neutralvibes/aca3f94da270f04a3cb30b7514123b53 to your computer and use it in GitHub Desktop.
Externally resolving and rejecting Javascript promises

Externally resolving and rejecting Javascript promises

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.

The Exploding Promise

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	
}

Usage

  • 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.

Testing

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!

The end

Hopes this helps someone. If there is a better way to do this please feel free to let me know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment