2

I am quite new to JavaScript and have a task for generating numbers in order of the functions being called with the use of callbacks.

The exercise should be done with a variable outside of the functions which should hold the returned values.

The starting code is as follows:

function asynchronousResponse(value, callback) {
  var delay = Math.floor(Math.random() * 10) * 1000;
  setTimeout(() => callback(value), delay);
}

function getAsyncNumber(number) {
  /* 
    Add implementation of getAsyncNumber function in a way that numbers
    appear on a console in order in which they have been called.

   Use asynchronousResponse to generate this responses.
  */
}

getAsyncNumber(0);
getAsyncNumber(1);
getAsyncNumber(2);
getAsyncNumber(3);
getAsyncNumber(4);

I am not clear on how this is supposed to work and how to check if the previous numbers have alreay been called out.

JKukielski
  • 31
  • 3

1 Answers1

1

The callback inside setTimeout is going to run in an async manner. Making use of the asynchronousResponse we can pass our own function as a callback. Notice the statement setTimeout(() => callback(value), delay);, this callback function will have access to our value and we can make use of that.

The implementation:

Now the idea is to keep storing the values as the functions are called. That way we have the definite order of our calls to getAsyncNumber. I think this refers to the variable outside the function which holds the returned values. We also keep a field for the status of the items. So we have an array of objects like {status,value}.

We update our array as our callbacks are called, but never log the resolved values. We only log something based on certain conditions. ONLY WHEN IT IS READY. Any resolved value will only be ready when everything before it is either already logged or in READY state.

Whenever any callback is called and returns a value, we check whether everything before the item is done, if yes, then we log the resolved value. If everything before it is in ready state, we log them too and then log our resolved value.

There is an edge case, where some items later in order are ready but they do not get logged. So as a cleanup, we keep track of the number of resolved values too using a counter variable. If all our items have been resolved then we just log everything in the array that is still in READY state.

Here is a working code:

function asynchronousResponse(value, callback) {
  var delay = Math.floor(Math.random() * 10) * 1000;
  setTimeout(() => callback(value), delay);
}

const vals = [];
let resolved = 0;

function getAsyncNumber(number) {
  vals[vals.length] = {status : "NOT_READY", number };
  const func = () => {
    resolved++;
    let ready = 0;
    let found = -1;
    for (let i = 0 ; i < vals.length;i++) {
      if (vals[i].number === number) {
        found = i;
        if (ready === i) {
          vals[i] = {status : "DONE", number : vals[i].number}
          for (let j= 0 ; j < i;j++) {
            if (vals[j].status === "READY") {
              vals[j] = {status : "DONE", number : vals[j].number}
              console.log(vals[j].number);
            }
          }
          console.log(number);
        } else {
          vals[i] = {status : "READY", number : vals[i].number}
        }
      } else if(found === -1) {
        if (vals[i].status === "READY" || vals[i].status === "DONE" ) {
          ready++;
        }
      }
    }
  
    if (resolved === vals.length) {
      for (let i = 0 ;i < vals.length;i++) {
        if (vals[i].status === "READY") {
          console.log(vals[i].number);
        }
      }
    }
  }
  asynchronousResponse(number,func);
}

getAsyncNumber('a');
getAsyncNumber('b');
getAsyncNumber(2);
getAsyncNumber(3);
getAsyncNumber(4);
getAsyncNumber('5');
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Tushar Shahi
  • 16,452
  • 1
  • 18
  • 39
  • 1
    "*We will be using Promises to solve this*" - but, you didn't? You did all the state management yourself, the `new Promise` wrapper is nothing but pointless decoration. – Bergi Oct 19 '22 at 20:09
  • @Bergi thanks. I just saw your point. Promises are probably not required, let me fix this – Tushar Shahi Oct 19 '22 at 20:26
  • Thanks for the update! Of course, using promises would have made everything simpler, but this is just as ok – Bergi Oct 19 '22 at 20:41
  • Do you mind adding an answer based on promises? It will help the me as much as it would help the OP – Tushar Shahi Oct 19 '22 at 20:43
  • See for example https://stackoverflow.com/a/54638606/1048572 – Bergi Oct 19 '22 at 20:48