Use Promise to wait until polled condition is satisfied

javascript wait for promise
wait for promise to resolve
javascript wait for callback to finish
javascript wait for asynchronous call to finish
javascript polling async/await
nodejs wait for promise
javascript poll until
typescript wait for function to finish

I need to create a JavaScript Promise that will not resolve until a specific condition is true. Let's say I have a 3rd party library, and I need to wait until a certain data condition exists within that library.

The scenario I am interested in is one where there is no way to know when this condition is satisfied other than by simply polling.

I can create a promise that waits on it - and this code works, but is there a better or more concise approach to this problem?

function ensureFooIsSet() {
    return new Promise(function (resolve, reject) {
        waitForFoo(resolve);
    });
}

function waitForFoo(resolve) {
    if (!lib.foo) {
        setTimeout(waitForFoo.bind(this, resolve), 30);
    } else {
        resolve();
    }
}

Usage:

ensureFooIsSet().then(function(){
    ...
});

I would normally implement a max poll time, but didn't want that to cloud the issue here.

A small variation would be to use a named IIFE so that your code is a little more concise and avoids polluting the external scope:

function ensureFooIsSet() {
    return new Promise(function (resolve, reject) {
        (function waitForFoo(){
            if (lib.foo) return resolve();
            setTimeout(waitForFoo, 30);
        })();
    });
}

Use Promise to wait until polled condition is satisfied · GitHub, Use Promise to wait until polled condition is satisfied - polling.js. je dois créer une promesse JavaScript qui ne se résoudra pas tant qu'une condition spécifique n'est pas vraie. Disons que j'ai une bibliothèque tierce partie, et j'ai besoin d'attendre jusqu'à ce qu'une certaine condition de données existe dans cette bibliothèque.

Is there a more concise approach to this problem?

Well, with that waitForFoo function you don't need an anonymous function in your constructor at all:

function ensureFooIsSet() {
    return new Promise(waitForFoo);
}

To avoid polluting the scope, I would recommend to either wrap both in an IIFE or to move the waitForFoo function inside the ensureFooIsSet scope:

function ensureFooIsSet(timeout) {
    var start = Date.now();
    return new Promise(waitForFoo);
    function waitForFoo(resolve, reject) {
        if (window.lib && window.lib.foo)
            resolve(window.lib.foo);
        else if (timeout && (Date.now() - start) >= timeout)
            reject(new Error("timeout"));
        else
            setTimeout(waitForFoo.bind(this, resolve, reject), 30);
    }
}

Alternatively, to avoid the binding that is needed to pass around resolve and reject you could move it inside the Promise constructor callback like @DenysSéguret suggested.

Is there a better approach?

Like @BenjaminGruenbaum commented, you could watch the .foo property to be assigned, e.g. using a setter:

function waitFor(obj, prop, timeout, expected) {
    if (!obj) return Promise.reject(new TypeError("waitFor expects an object"));
    if (!expected) expected = Boolean;
    var value = obj[prop];
    if (expected(value)) return Promise.resolve(value);
    return new Promise(function(resolve, reject) {
         if (timeout)
             timeout = setTimeout(function() {
                 Object.defineProperty(obj, prop, {value: value, writable:true});
                 reject(new Error("waitFor timed out"));
             }, timeout);
         Object.defineProperty(obj, prop, {
             enumerable: true,
             configurable: true,
             get: function() { return value; },
             set: function(v) {
                 if (expected(v)) {
                     if (timeout) cancelTimeout(timeout);
                     Object.defineProperty(obj, prop, {value: v, writable:true});
                     resolve(v);
                 } else {
                     value = v;
                 }
             }
         });
    });
    // could be shortened a bit using "native" .finally and .timeout Promise methods
}

You can use it like waitFor(lib, "foo", 5000).

JavaScript: Promises and Why Async/Await Wins the Battle, Promises provide a simpler alternative for executing, composing and managing Fulfilled - the asynchronous operation has completed, and the The correct way to approach this type of situation is to use Promise.all(). Schedules a command to wait for a condition to hold, as defined by some user supplied function. If any errors occur while evaluating the wait, they will be allowed to propagate. In the event a condition returns a webdriver.promise.Promise, the polling loop will wait for it to be resolved and use the resolved value for evaluating whether the condition has been satisfied.

Here's a utility function using async/await and default ES6 promises. The promiseFunction is an async function (or just a function that returns a promise) that returns a truthy value if the requirement is fulfilled (example below).

const promisePoll = (promiseFunction, { pollIntervalMs = 2000 } = {}) => {
  const startPoll = async resolve => {
    const startTime = new Date()
    const result = await promiseFunction()

    if (result) return resolve()

    const timeUntilNext = Math.max(pollIntervalMs - (new Date() - startTime), 0)
    setTimeout(() => startPoll(resolve), timeUntilNext)
  }

  return new Promise(startPoll)
}

Example usage:

// async function which returns truthy if done
const checkIfOrderDoneAsync = async (orderID) => {
  const order = await axios.get(`/order/${orderID}`)
  return order.isDone
}

// can also use a sync function if you return a resolved promise
const checkIfOrderDoneSync = order => {
  return Promise.resolve(order.isDone)
}

const doStuff = () => {
  await promisePoll(() => checkIfOrderDone(orderID))
  // will wait until the poll result is truthy before
  // continuing to execute code
  somethingElse()
}

Polling with async/await - DEV Community ‍ ‍ , I have been using the following piece of code for some polling await fn(); } return result; } function wait(ms = 1000) { return new Promise(resolve toEqual(3​); }); it("calls api many times while condition is satisfied", async  Wait until a condition is satisfied. Contribute to InterAl/wait-for-cond development by creating an account on GitHub.

function getReportURL(reportID) {
  return () => viewReportsStatus(reportID)
  .then(res => JSON.parse(res.body).d.url);
}

function pollForUrl(pollFnThatReturnsAPromise, target) {
  if (target) return P.resolve(target);
  return pollFnThatReturnsAPromise().then(someOrNone => pollForUrl(pollFnThatReturnsAPromise, someOrNone));
}

pollForUrl(getReportURL(id), null);

Promise, To learn about the way promises work and how you can use them, A pending promise can either be fulfilled with a value, or rejected with a reason (error). is no race condition between an asynchronous operation completing Promise.​race(iterable): Wait until any of the promises is resolved or rejected. GitHub Gist: star and fork shussekaido's gists by creating an account on GitHub.

Here's a waitFor function that I use quite a bit. You pass it a function, and runs it until the function returns a truthy value, or until it times out. Example usages:

// wait for an element to exist, then assign it to a variable 
let bed = await waitFor(()=>document.getElementById('_1vd7r9f'))
if(!bed) doSomeErrorHandling();
// wait for a variable to be truthy
await waitFor(()=>el.loaded)
// wait for some test to be true
await waitFor(()=>video.currentTime>21)
// add a specific timeout
await waitFor(()=>video.currentTime>21, 60*1000)
// send an element as an argument once it exists
doSomething(await waitFor(()=>selector('...'))
// pass it some other test function
if(await waitFor(someTest)) console.log('test passed')
else console.log("test didn't pass after 20 seconds")

This is the code for it

function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms));    }
/* Waits for test function to return a truthy value
example usage:
    // wait for an element to exist, then save it to a variable
    var el = await waitFor(()=>$('#el_id')))                 // second timeout argument optional, or defaults to 20 seconds
 */
async function waitFor(test, timeout_ms=20*1000){
    return new Promise(async(resolve,reject)=>{
        if( typeof(timeout_ms) != "number") reject("Timeout argument not a number in waitFor(selector, timeout_ms)");
        var freq = 100;
        var result
        // wait until the result is truthy, or timeout
        while( result === undefined || result === false || result === null || result.length === 0 ){  // for non arrays, length is undefined, so != 0
            if( timeout_ms % 1000 <freq)        console.log('%c'+'waiting for: '+ test,'color:#809fff' );
            if( (timeout_ms -= freq) < 0 ){     console.log('%c'+'Timeout : '   + test,'color:#cc2900' );
                resolve(false);
                return;
            }
            await sleep(freq);
            result = typeof(test) === 'string' ? eval(test) : test();       // run the test and update result variable
        }
        // return result if test passed
        console.log('Passed: ', test);
        resolve(result);
    });
}

Polling in JavaScript, For example, we can use polling if there is data that changes frequently or… Then on the server, we wait for the response from the authentication provider function returns a promise and will run recursively until a stopping condition is met. Use Promise to wait until polled condition is satisfied. I need to create a JavaScript Promise that will not resolve until a specific condition is true. Let's say I have a 3rd party library, and I need to wait until a certain data condition exists within that library.

The Economist, compensated—but to. insist that the Baltic Fleet should not proceed until an justified, but required by the unprecedented character of the situation created by the our fishermen to wait for investi gation and punishment until those guilty of it have And there will be universal satisfaction here if, without the necessity for any  48 Use Promise to wait until polled condition is satisfied 24 How to disable TypeScript compilation in .Net Core projects? 21 What's the difference between this.function and prototype.function?

selenium-webdriver.WebDriver, Either a known session or a promise that will be resolved to a session. executor, Executor. The executor to use when sending commands to the browser. The Promise.all() method returns a single Promise that resolves when all of the promises passed as an iterable have resolved or when the iterable contains no promises. It rejects with the reason of the first promise that rejects. There is no implied ordering in the execution of the array of Promises given.

Polling with Redux - Big Bite, Redux-saga uses ES6 generator functions to make asynchronous flow easy to read. What we will accomplish is a poll that runs every 4 seconds, and will wait for redux-saga delay utility function, which returns a promise that resolves after a specified amount of time. Happy polling! Privacy Policy · Terms & Conditions. Make a promise, waiting for a specified amount of time, util something is done. Syntactic sugar for setTimeout and setInterval. Based on ES6 Promise.

Comments
  • This looks OK. You don't really need to pollute the external scope with waitForFoo but it's a detail and depends on the rest of the code. Are you using native promises or a specific library ?
  • agreed - this is just a snippet of overall code. This would use native Promise. I've had this pattern come up a time or two and interested if there's a better way to structure this.
  • An easier approach would be to Object.observe the library object
  • @BenjaminGruenbaum, very nice. I was hoping for something like that. Depending on browser requirements, I may not be able to use it, but that's a good tip.
  • Well, then polyfill it in older browsers.
  • I was wanting to use an IIFE, but did not think about naming it.