Skip to content

Instantly share code, notes, and snippets.

@spudly spudly/abortable.js
Last active Jun 30, 2016

Embed
What would you like to do?
Abort your promises!
const abortable = promiseMaker => (...args) => {
let aborted = false;
const promise = new Promise((resolve, reject) => {
const resolveIfNotAborted = resolution => {
if (aborted) {
reject(Object.assign(Error('Promise Aborted'), {code: 'PROMISE_ABORTED'}));
}
resolve(resolution);
};
promiseMaker(...args).then(resolveIfNotAborted, reject);
});
promise.abort = () => {
aborted = true;
};
return promise;
};
export default abortable;
import abortable from './abortable';
const names = ['John', 'Mary', 'William', 'Helen', 'James', 'Dorothy', 'Robert', 'Margaret', 'Joseph', 'Ruth', 'George', 'Anna', 'Charles', 'Mildred', 'Edward', 'Elizabeth', 'Frank', 'Frances', 'Walter', 'Marie', 'Thomas', 'Evelyn', 'Henry', 'Alice', 'Paul', 'Florence', 'Harold', 'Virginia', 'Albert', 'Rose', 'Raymond', 'Lillian', 'Richard', 'Louise', 'Arthur', 'Catherine', 'Harry', 'Edna', 'Louis', 'Gladys', 'Ralph', 'Ethel', 'Clarence', 'Irene', 'Donald', 'Josephine', 'Carl', 'Ruby', 'Willie', 'Grace', 'Howard', 'Thelma', 'Jack', 'Martha', 'Fred', 'Eleanor', 'David', 'Hazel', 'Kenneth', 'Lucille', 'Francis', 'Edith', 'Roy', 'Gertrude', 'Earl', 'Annie', 'Joe', 'Pauline', 'Samuel', 'Esther', 'Lawrence', 'Doris', 'Anthony', 'Clara', 'Ernest', 'Beatrice', 'Stanley', 'Emma', 'Michael', 'Ann', 'Alfred', 'Bertha', 'Herbert', 'Julia', 'Eugene', 'Bernice', 'Andrew', 'Agnes', 'Leonard', 'Marjorie', 'Elmer', 'Elsie', 'Leo', 'Sarah', 'Peter', 'Katherine', 'Russell', 'Ida', 'Bernard', 'Marion', 'Herman', 'Lois', 'Frederick', 'Eva', 'Edwin', 'Anne', 'Norman', 'Jean', 'Daniel', 'Bessie', 'Chester', 'Pearl', 'Lester', 'Viola', 'Floyd', 'Mabel', 'Melvin', 'Laura', 'Leroy', 'Myrtle', 'Vincent', 'Nellie', 'Clifford', 'Betty', 'Clyde', 'Kathryn', 'Theodore', 'Jessie', 'Charlie', 'Stella', 'Lloyd', 'Willie', 'Sam', 'Minnie', 'Philip', 'Vera', 'Milton', 'Alma', 'Benjamin', 'Sylvia', 'Woodrow', 'Jane', 'Lewis', 'Ella', 'Martin', 'Lucy', 'Ray', 'Lillie', 'Marvin', 'Lena', 'Victor', 'Genevieve', 'Oscar', 'Jennie', 'Alvin', 'Mattie', 'Cecil', 'Leona', 'Stephen', 'Blanche', 'Gerald', 'Vivian', 'Jesse', 'Barbara', 'Vernon', 'Violet', 'Lee', 'Marguerite', 'Leon', 'Mae', 'Morris', 'Ellen', 'Edgar', 'Rita', 'Gordon', 'Charlotte', 'Sidney', 'Opal', 'Everett', 'Marian', 'Glenn', 'Carrie', 'Willard', 'Theresa', 'Claude', 'Velma', 'Maurice', 'Juanita', 'Harvey', 'Wilma', 'Wilbur', 'Beulah', 'Arnold', 'Hattie', 'Alexander', 'Emily', 'Max', 'Fannie', 'Irving', 'Sophie'];
const fetchUsers = abortable(({startsWith}) => {
const users = names.filter(name => name[0] == startsWith);
return new Promise(resolve => {
setTimeout(resolve.bind(null, users), 500)
});
});
const handleSuccess = ::console.log;
const handleError = error => {
if (error.code === 'PROMISE_ABORTED') {
console.log('aborted');
return;
}
throw error;
};
let promise;
['A', 'B', 'C', 'D', 'E'].forEach(letter => {
if (promise) {
promise.abort();
}
promise = fetchUsers({startsWith: letter});
promise.then(handleSuccess, handleError);
});
import abortable from './abortable';
import ErrorWrapper from 'error-wrapper';
class TimeoutError extends ErrorWrapper {
get code() {
return 'TIMEOUT';
}
}
const timeout = (time, promiseMaker) => async (...args) => {
args.slice(); // workaround babel bug. see https://phabricator.babeljs.io/T7260
const promise = abortable(promiseMaker)(...args);
const timer = setTimeout(::promise.abort, time);
try {
const result = await promise;
clearTimeout(timer);
return result;
} catch (error) {
if (error.code === 'PROMISE_ABORTED') {
throw new TimeoutError('Timed Out', error);
}
throw error;
}
};
export default timeout;
@spudly

This comment has been minimized.

Copy link
Owner Author

commented Jun 30, 2016

TODO: make this into an npm package

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.