Search code examples
javascriptjqueryasynchronoussettimeoutq

add a delay(synchronous) working with modern browsers except IE


Working code: in Chrome, Firefox

let sleep = function (ms) {
   return new Promise(resolve => setTimeout(resolve, ms))
};

And somewhere in my function i use async,await to make the delay synchronous

function updateHandler(newTags, tagName, contentIds) {
    let deferred = Q.defer(),
        counter = 0,
        failedIDS = [],
        data = {};
    data["contentIds"] = contentIds;
    data["failedIDS"] = failedIDS;
    if (contentIds.length === 0) {
        return Promise.resolve(data);
    }
     //aync and await is here
    _.forEach(contentIds, async function (contentId) {
        //wait for some time and continue
        await sleep(150);

        let tags = [], activity;

        //API hits..
        osapi.jive.core.get({
            v: "v3",
            href: "/contents/" + contentId + ""
        }).execute(function (content) {
            tags = content.tags;
            activity = content["updated"];
            content["tags"] = _.union(tags, newTags);
            osapi.jive.core.put({
                v: "v3",
                href: "/contents/" + contentId + "",
                body: content,
                "minor": "true",
                "updated": activity
            }).execute(function (response) {
                    counter++;
                    if (response.error) {
                        failedIDS.push(contentId);
                    }
                    if (counter === contentIds.length) {
                        deferred.resolve(data);
                    }
                }, function (error) {
                    counter++;
                    failedIDS.push(contentId);
                    if (counter === contentIds.length) {
                        deferred.resolve(data);
                    }
                }
            );
        })
    });
    return deferred.promise;
};

So a 0.15 seconds is must for this api hit to work and update all the items.

Since async and await won't work in IE, I wanted to write a basic wait(ms) function which waits for 0.15 seconds.

Note: So, without sleep() function, above loop works fine for the first iteration and fails for the second iteration and terminates the code execution. SO a must 0.15 seconds delay for each iteration is needed, this is the product limitation.

setTimeout() is asynchronous.. so i didn't use it.

Below code works for me.. But it's not what I want, because the browser runs out of memory and more CPU utilization, expensive..

function wait(ms) {
  console.log("started............");
    var start = Date.now(),
        now = start;
    while (now - start < ms) {
      now = Date.now();
    }
  console.log("finished............");
}

Question: I want to have atleast 0.15 seconds delay for each iteration, how can I achieve it.

++ I tried the following way, picture here. Successfully updates only 16 to 19 contents, out of 100 iterable items and then throws the same error as it does when without sleep() function. enter image description here


Solution

  • Say I need to run this request function every 150ms:

    const request = () => new Promise(res => setTimeout(() => { console.log('done'); res() }, 1000))
    //
    

    Then I can use setTimeout recursively to add a delay between each request:

    let counter = 0;
    
    // this handler will be passed into a setTimeout
    // to kick off the whole thing
    const handler = () => {
      console.log(counter);
    
      // request api thing
      request().then(() => {
        counter++;
        if (counter === 100) return;
        setTimeout(handler, 150) // remove this
      })
    }
    
    // kick off
    setTimeout(handler, 150)
    

    It makes sure each request is finished before waiting to run the next one.