“It’ll resolve eventually, I promise!”

When programming in JavaScript, Promises are an elegant way of handling values that will be available after some asynchronous operation completes. One trick I particularly like is making Promises for a user-retriable operation that will eventually resolve with the proper value, no matter which try is the one that succeeds.

For a function that handles the retry UI itself and returns such a Promise:

function magic() {
	// You'd do asynchronous work, declaring "promise" with a Promise
	// and "nextAttempt" with a Promise-returning function, and then...
	return promise.catch( function catcher(error) {
		var waitOnUser = new Promise( function(resolve) {
			// Show UI to the end user; call resolve when they request a retry
		} );
		return waitOnUser.then(nextAttempt).catch(catcher);
	} );
}

If you’d prefer to leave the retry UI to the function’s consumer (only recommended if only a single consumer directly handles the return value):

function magic() {
	// Declare "promise" and "nextAttempt" as above, then...
	return promise.catch( function catcher(error) {
		var endWait;
		var waitOnUser = new Promise( function(resolve) {
			endWait = resolve;
		} );
		return {
			error: error,
			retry: endWait,
			retryResult: waitonUser.then(nextAttempt)
		};
	} );
}
// The consumer's rejection handler, if named "handler" with a parameter "obj",
// would return obj.retryResult.catch(handler)

Deviant Love uses a variant of the second version above – rather than return a promise directly, researchLove returns an object with multiple Promises and various methods to act on operations in progress, and retry is a method of said object rather than included with a rejection value.

Naturally, this pattern is useful only if magic can use partially-completed work across attempts. If it would have to throw out everything and start over for a new attempt, the KISS principle dictates you should just call magic again when the user requests a retry.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s