0

I have a async fetch function that waits 2 seconds and returns a object:

async function fetch() {
    var object;
    await setTimeout(() => { object = { name: 'User', data: 'API Data' } }, 2000);
    return object;
}

I want to display the object when the initialization is completely done (after 2 seconds)

fetch().then((val) => {
    console.log("DONE!"); 
    console.log(val.name);
}).catch((err) => {
    console.log("ERROR!");
    console.log(err);
});

The code prints both DONE and ERROR Cannot read properties of undefined (reading 'name')

I have tried with Promise, no luck

let promise = new Promise((resolve, reject) => {
    let request = fetch();
    if (request !== undefined)
        resolve(request);
    else
    reject(request);

}).then((val) => {
    console.log(val);
});

How can I properly check that fetch() has returned a value before printing without changing the inside of the function. I can delete the async and await in it but I am unable to edit it (I.E. adding a Promise inside)

Lepy
  • 152
  • 1
  • 12

3 Answers3

1

Based on requirement

I can delete the async and await in it (fetch function) but I am unable to edit it (I.E. adding a Promise inside)

The only way I see is to override window.setTimeout function to make it to return a promise. That way you will be able to await it and there will be no need to modify your fetch function.

const oldTimeout = window.setTimeout;
window.setTimeout = (fn, ms) => {
  return new Promise((resolve, reject) => {
    oldTimeout(() => {
      fn();
      resolve();
    }, ms);
  });
};

async function fetch() {
  var object;
  await setTimeout(() => {
    object = { name: "User", data: "API Data" };
  }, 2000);
  return object;
}

fetch()
  .then((val) => {
    console.log("DONE!");
    console.log(val.name);
  })
  .catch((err) => {
    console.log("ERROR!");
    console.log(err);
  });

NOTE: For anyone without this requirement - please, use other answers to this question or check await setTimeout is not synchronously waiting for additional details/explanations. This kind of overridings are very confusing due to everyone expect common and well-known functions to behavior in a way described in the docs.

Sergey Sosunov
  • 4,124
  • 2
  • 11
  • 15
1

You cannot await the setTimeout function, this is because your function returns undefined. You have used the promise in the wrong way. Below code will fix your issue.

function fetch() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve({ name: "User", data: "API Data" });
        }, 2000);
    });
}

fetch()
    .then((val) => {
        console.log("DONE!");
        console.log(val.name);
    })
    .catch((err) => {
        console.log("ERROR!");
        console.log(err);
    });

And remember that there is no need to change the setTimeout function.

inceenes10
  • 46
  • 1
  • 6
0

The problem is that setTimeout does not actually return a promise, which means you cannot use await with setTimeout, that's why the var object; is returned instantly as undefined.

To solve this issue, you simply need to wrap setTimeout around a promise. Like so:

function setTImeoutAwait(time) {
    return new Promise((resolve) => {
        setTimeout(resolve, time);
    });
}

You can then use it like this:

async function fetch() {
    var object;
    await setTImeoutAwait(1000).then(() => {
        object = { name: "test" };
    });
    return object;
}
Abdullah Hejazi
  • 277
  • 2
  • 8