-1

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

ggorantala
  • 196
  • 2
  • 16
  • Why not just using setTimeout with your further code in the callback? – moronator Mar 12 '19 at 14:58
  • I tried that, if the iterable items are 100 then it updates for range 16 to 19 and then throws the same error( which i used to get when running without `sleep()` ) – ggorantala Mar 12 '19 at 15:00
  • What about defining an array with your items and then setting a timeout to a function in which the first item will be passed to your api. After that the function would set another timeout to itself – moronator Mar 12 '19 at 15:05
  • Shouldn't the server notify you when it's done and ready for another operation. Waiting 150ms doesn't seem safe to me, I might be wrong though... – Jonas Grumann Mar 12 '19 at 15:06
  • @moronator I thought of that idea but I had a promise resolving my success IDs. So I thought it will be a mess of promises.. and need to write promise.all()... I am I wrong ? – ggorantala Mar 12 '19 at 15:08
  • @JonasGrumann : yes.. true. Even I am not happy with this workaround.. I reported this BUG with our product team.. But our management are desperate and asked me to implement a workaround. And this is the reason me being implementing this.. :( – ggorantala Mar 12 '19 at 15:12
  • You could switch to events, then you could trigger the events from your repetitive function when it receives a success id from the server and you could subscribe to these events where you need it – moronator Mar 12 '19 at 15:13
  • @moronator : this looks interesting, possibly firing events and subscribing them.. can you help me with an example please.. – ggorantala Mar 12 '19 at 15:15
  • 1
    @gopigorantala You may read [this mozilla article](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events) – moronator Mar 12 '19 at 15:23
  • 1
    Have you tried a recursive setTimeout? It should guarantee a delay between each subsequent requests – Derek Nguyen Mar 12 '19 at 15:34
  • @DerekNguyen, I never tried that. how will that guarantee a delay ? – ggorantala Mar 12 '19 at 17:50
  • @JonasGrumann, I am doing the same in my code. I get a success, resolve it and then i increase the counter, go to the next item and so on.. – ggorantala Mar 12 '19 at 17:52

1 Answers1

0

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.

Derek Nguyen
  • 11,294
  • 1
  • 40
  • 64
  • I have a recursive function call ex: `updateHandler(a,b,c).then(...)` and in `then()` I check if check for failedIds.. and if they `!=0` then call the same recursive fn. Let me try your approach within the iteration and resolve the promise.. – ggorantala Mar 13 '19 at 06:25
  • Thank you.. this solution worked for me.. though I need to make the promise compatible to IE – ggorantala Mar 13 '19 at 11:26
  • `` adding this made the Promise work like a charm.. – ggorantala Mar 13 '19 at 14:13
  • glad it helps. I had to develop for ie11 a few times in the past and [polyfill.io](https://polyfill.io) is a god-send! – Derek Nguyen Mar 14 '19 at 04:52
  • since each `promise` is resolved.. I made the timeout's to 0 instead of 150millis.. its more optimised with performance.. beware placing 0 also adds some delay to `setTimeout` for 16 to 20millis.. ref:[event-loop](https://www.youtube.com/watch?v=8aGhZQkoFbQ) (awesomely explained..).. watch this video till the end, it will make more sense how event loop works in a single threaded environment(JS). – ggorantala Mar 15 '19 at 10:50