Polling Until Getting Specific Result?
Solution 1:
Here's an more extensible solution based on the post polling with async/await
Just add the following utility methods:
const poll = asyncfunction (fn, fnCondition, ms) {
let result = awaitfn();
while (fnCondition(result)) {
awaitwait(ms);
result = awaitfn();
}
return result;
};
const wait = function (ms = 1000) {
returnnewPromise(resolve => {
setTimeout(resolve, ms);
});
};
Then you can call it like this:
letfetchReport = () => axios.get(reportUrl);
letvalidate = result => !result.data.summary;
let response = awaitpoll(fetchReport, validate, 3000);
Solution 2:
Recent versions of Node.js, have support for async / await.
Below is an example of using it..
One major advantage of async / await, it's very easy to follow the code, and understand it's logic. If for example you wanted to extend this, to have a max try's feature, it would be trivial to do. (hint) It's just a for loop :)
let count = 0;
var client = {
get: function () {
returnnewPromise(function (resolve, reject) {
count ++;
setTimeout(function () {
if (count > 4) resolve({status:'DONE',otherStuff:'Other Stuff'});
elseresolve({status: `count: ${count}`});
}, 1000);
});
}
}
asyncfunctionsomeFunction() {
while (true) {
let dataResult = await client.get('/status');
console.log(dataResult.status);
if (dataResult.status == "DONE") {
return dataResult;
}
}
}
(async () => { let r = awaitsomeFunction(); console.log(r); })();
Solution 3:
Here's an example of a function that uses promises and polls until you get the desired result. I've also parameterized it so that you can pass in the polling interval and a timeout value:
// create a promise that resolves after a short delayfunctiondelay(t) {
returnnewPromise(function(resolve) {
setTimeout(resolve, t);
});
}
// interval is how often to poll// timeout is how long to poll waiting for a result (0 means try forever)// url is the URL to requestfunctionpollUntilDone(url, interval, timeout) {
let start = Date.now();
functionrun() {
return client.get(url).then(function(dataResult) {
if (dataResult.status === "DONE") {
// we know we're done here, return from here whatever you // want the final resolved value of the promise to bereturn dataResult;
} else {
if (timeout !== 0 && Date.now() - start > timeout) {
thrownewError("timeout error on pollUntilDone");
} else {
// run again with a short delayreturndelay(interval).then(run);
}
}
});
}
returnrun();
}
// sample usage// polls every 500ms for up to 30 secondspollUntilDone(someUrl, 500, 30 * 1000).then(function(result) {
// have final result here
}).catch(function(err) {
// handle error here
});
The key here is to chain your promises so each time you call run()
again, you return its value so it is chained to the prior promise. Then, whenever you finally return a value or throw an exception, the original promise will get that value or error as the resolved value or rejected reason.
Note that I added a timeout because you really never want to be polling forever, particularly in cases where some unforeseen and recurring error might not reject the promise, but won't get you the result you want.
Solution 4:
I just had to solve a similar problem. Below is a gist of my solution:
// api call with interval until receiving a specific data.constcallApi = () => {
returnnewPromise((resolve, reject) => {
console.log('calledAPI!');
setTimeout(()=>{
var myNumber = parseInt(Math.random()*10, 10);
resolve(myNumber);
}, 1000);
});
}
constcallIntervalFunc = () => { // need to wrap it with a function because setInterval is not a function and cannot call it from outside otherwise.const callInverval = setInterval(async()=>{
console.log('checking the api...');
var responseNumber = awaitcallApi();
console.log('Got response! ',responseNumber);
if (responseNumber === 5) {
clearInterval(callInverval);
console.log('responseNumber is 5!! ends.');
}
}, 2000);
}
callIntervalFunc();
Solution 5:
Following continuousPromise
method will do the job, it requires 2 parameters:
Promise responsible for fetching data
delay (in ms) in subsequent calls
let exit = false; constcontinuousPromise = (promise, interval) => { constexecute = () => promise().finally(waitAndExecute); constwaitAndExecute = () => { if (exit) { return; } setTimeout(execute, interval) }; execute(); }
How to use
continuousPromise(() => {
return axios.get("something.json")
.then((res) => {
if (res && res.status !== 'PENDING') { // Check here for expected result
exit = true;
}
})
.catch((error) => {
exit = true;
console.log(error);
})
}, 1000);
Post a Comment for "Polling Until Getting Specific Result?"