Skip to content

Instantly share code, notes, and snippets.

@briancavalier
Last active August 29, 2015 14:10
Show Gist options
  • Select an option

  • Save briancavalier/c416d396e844e31c6efa to your computer and use it in GitHub Desktop.

Select an option

Save briancavalier/c416d396e844e31c6efa to your computer and use it in GitHub Desktop.
function AbortablePromise(resolver) {
if (typeof resolver !== 'function')
throw new Error('AbortablePromise needs a resolver function');
var abort;
var promise = new Promise(function (resolve, reject) {
var aborter;
abort = function () {
if (aborter == null)
return;
var fn = aborter;
aborter = null;
try {
return fn.apply(this, arguments);
} catch (error) {
reject(error);
}
};
// Resolver should return an aborter
aborter = resolver(function (child) {
if (child && typeof child.abort === 'function') {
aborter = child.abort;
} else {
aborter = null;
}
resolve.apply(this, arguments);
}, function () {
aborter = null;
reject.apply(this, arguments);
});
if(typeof aborter !== 'function') {
// Make rejecting be the default abort behavior.
// Not sure if this is good or bad, but maybe worth discussion
aborter = reject;
}
});
return makeAbortable(promise, abort);
}
function AbortablePromise(resolver) {
if (typeof resolver !== 'function')
throw new Error('AbortablePromise needs a resolver function');
var abort;
var promise = new Promise(function (resolve, reject) {
var aborter;
abort = function () {
if (aborter == null)
return;
var fn = aborter;
aborter = null;
var abortResult;
try {
// aborter may return a promise to control the state of
// the promise, rather than having to capture the
// resolve/reject functions
abortResult = fn.apply(this, arguments);
resolve(abortResult);
return abortResult;
} catch (error) {
reject(error);
}
};
// Resolver should return an aborter
aborter = resolver(function (child) {
if (child && typeof child.abort === 'function') {
aborter = child.abort;
} else {
aborter = null;
}
resolve.apply(this, arguments);
}, function () {
aborter = null;
reject.apply(this, arguments);
});
if(typeof aborter !== 'function') {
// Make rejecting be the default abort behavior.
// Not sure if this is good or bad, but maybe worth discussion
aborter = reject;
}
});
return makeAbortable(promise, abort);
}
@mjackson
Copy link

mjackson commented Dec 8, 2014

var promise = new AbortablePromise(function (resolve, reject) {
  // Use resolve & reject as you normally would.
  var request = makeRequest( ... , function (error, response) {
    if (error) {
      reject(error);
    } else {
      resolve(response);
    }
  });

  // Return the function you want to use as promise.abort. So, e.g.
  // you could return `reject` here to reject this promise when it
  // is aborted. This is the default behavior if you don't return
  // anything.
  return reject;

  // Or return a custom abort function. In this case, it is your
  // responsibility to resolve/reject as needed.
  return function () {
    request.abort();

    // We don't have to close over resolve/reject. Instead, we can just
    // return/throw as we would in any other .then() clause.
    throw new Error('Request was aborted');
  };

  // Or return `resolve` if you want abort to resolve for some reason.
  return resolve;
});

promise.abort(); // Calls the function you returned from your resolver.

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