I am trying to create an asynchronous polling function that checks the database periodically to see if a value exists. However, I want to give the user the ability to cancel this request. What is the proper way to trigger an asynchronous process to exit early? I have tried exposing the reject function outside of the polling function, but was not able to get it to work. Currently I am setting a boolean variable called cancelRequest
in the function's outer scope and then trying to check if that value has been set to true via the method shouldCancel
. That method is triggered when a user clicks a cancel button. If shouldCancel
resolves to true, reject and break out early. This works, but not all the time. My guess is that the async polling process is continuing to execute before the other method updates the cancelRequest
variable.
With that being said, does anyone have any tips or ideas of how I can implement a cancellable polling function that runs an asynchronous task? I've included my code below.
Thank you all very much in advance!
exports.pollForPortfolio = async (porfolioId) => {
return poll({
fn: () => this.getPortfolio(porfolioId),
validate: validatePortfolioRequest,
interval: 5000,
maxAttempts: 50
})
.then(portfolio => {
return portfolio
})
.catch(err => console.error(err));
}
const poll = async ({ fn, validate, interval, maxAttempts }) => {
let attempts = 0;
const executePoll = async (resolve, reject) => {
const result = await fn();
attempts++;
console.log("poll result attempt #", attempts + ": " + JSON.stringify(result));
if (validate(result.finished)) {
return resolve(result);
} else if (shouldCancel()) {
cancelRequest = false;
return reject(new Error('Request cancelled'));
} else if (maxAttempts && attempts === maxAttempts) {
return reject(new Error('Exceeded max attempts'));
} else {
setTimeout(executePoll, interval, resolve, reject);
}
};
return new Promise(executePoll);
};
exports.getUserPortfolio = function(portfolioId) {
return new Promise(function (resolve, reject) {
// query server here to see if value is available
request(options, function (error, response, data) {})
}
}