JS Promise函数调用返回对象

huangapple go评论79阅读模式
英文:

JS Promise function call that returns object

问题

I have a async fetch function that waits 2 seconds and returns an 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).

英文:

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)

答案1

得分: 1

基于要求,

> 我可以删除其中的async和await(在fetch函数中),但我无法编辑它(即添加一个Promise)

我唯一能想到的方法是覆盖window.setTimeout函数,使其返回一个Promise。这样你就可以等待它,而不需要修改你的fetch函数。

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

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);
});

<!-- end snippet -->

注意:对于没有这个要求的人,请使用其他答案或查看await setTimeout is not synchronously waiting以获取更多详细信息/解释。这种覆盖可能会让人感到困惑,因为每个人都希望常见和众所周知的函数在文档中描述的方式中运行。

英文:

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.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

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

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

fetch()
  .then((val) =&gt; {
    console.log(&quot;DONE!&quot;);
    console.log(val.name);
  })
  .catch((err) =&gt; {
    console.log(&quot;ERROR!&quot;);
    console.log(err);
  });

<!-- end snippet -->

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.

答案2

得分: 1

你不能等待setTimeout函数,这是因为你的函数返回undefined。你使用了promise的方式不正确。下面的代码将修复你的问题。

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

fetch()
    .then((val) => {
        console.log("完成!");
        console.log(val.name);
    })
    .catch((err) => {
        console.log("错误!");
        console.log(err);
    });

并且请记住不需要更改setTimeout函数。

英文:

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) =&gt; {
        setTimeout(() =&gt; {
            resolve({ name: &quot;User&quot;, data: &quot;API Data&quot; });
        }, 2000);
    });
}

fetch()
    .then((val) =&gt; {
        console.log(&quot;DONE!&quot;);
        console.log(val.name);
    })
    .catch((err) =&gt; {
        console.log(&quot;ERROR!&quot;);
        console.log(err);
    });

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

答案3

得分: 0

问题在于 setTimeout 实际上不会返回一个 Promise,这意味着你无法在 setTimeout 中使用 await,这就是为什么 var object; 会立即返回为 undefined 的原因。

要解决这个问题,你只需要将 setTimeout 包装在一个 Promise 中,就像这样:

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

然后你可以这样使用它:

async function fetch() {
    var object;
    await setTImeoutAwait(1000).then(() => {
        object = { name: "test" };
    });
    return object;
}
英文:

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) =&gt; {
        setTimeout(resolve, time);
    });
}

You can then use it like this:

async function fetch() {
    var object;
    await setTImeoutAwait(1000).then(() =&gt; {
        object = { name: &quot;test&quot; };
    });
    return object;
}

huangapple
  • 本文由 发表于 2023年1月8日 23:44:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/75049122.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定