我正在尝试异步/等待功能。我有这样的代码模仿请求:
const getJSON = async () => {
const request = () => new Promise((resolve, reject) => (
setTimeout(() => resolve({ foo: 'bar'}), 2000)
));
const json = await request();
return json;
}
当我以这种方式使用代码时
console.log(getJSON()); // returns Promise
它返回一个 Promise
但是当我调用这行代码时
getJSON().then(json => console.log(json)); // prints { foo: 'bar' }
它按预期打印 json
是否可以只使用像
console.log(getJSON())
这样的代码?我不明白什么?
每个
async
函数都会返回一个 Promise
对象。 await
语句对 Promise
进行操作,等待 Promise
resolve
或 reject
s。
所以不,即使您使用
console.log
,也不能直接对异步函数的结果执行 await
。使用 await
会让你的函数等待,然后返回一个 Promise
,它会立即解析,但它不会为你解开 Promise
。您仍然需要使用 Promise
或使用 async
来解开 await
函数返回的 .then()
。
当您使用
.then()
而不是直接使用 console.log
时,.then()
方法将使 Promise 的结果可供您使用。但是你无法从Promise的outside得到
Promise
的结果。这是使用 Promise 的模型的一部分。
使用
async
定义的函数始终返回 Promise
。如果您返回不是 Promise
的任何其他值,它将隐式包装在 Promise
中。 语句 const json = await request();
将 Promise
返回的 request()
解包为普通对象 { foo: 'bar' }
。然后,在从 Promise
返回之前,将其包装在 getJSON
中,因此当您调用 Promise
时,最终会得到 getJSON()
。因此,要解开它,您可以像您所做的那样调用 getJSON().then()
或执行 await getJSON()
来获取解析值。
const getResOrErr = () => {
const callAsyncCodeHere = async () => {
const request = () =>
new Promise((resolve, reject) =>
setTimeout(() => resolve({ foo: "bar" }), 2000)
);
const json = await request();
return json;
};
return callAsyncCodeHere()
.then(console.log)
.catch(console.log);
};
getResOrErr();
试试这个。您可以在主函数中创建一个函数,然后将 Promise 代码放入该函数中。在那里调用它,当您收到响应或错误时,只需返回它即可。
其他答案已经解释了“每个异步函数都返回一个 Promise 对象”,但我猜这种混乱也可能来自这样一个事实:您总是需要在异步函数实现中编写
await
两次(getJSON()
在您的case),一个用于该异步函数的调用者。
正如 MDN 中等待的控制流效果 所解释的,
当代码中遇到等待时(无论是在异步函数中还是在 在模块中),等待的表达式被执行,而所有代码 取决于表达式的值被暂停并推入 微任务队列。然后主线程被释放以用于下一个任务 事件循环。即使等待的值是一个,也会发生这种情况 已经解决的承诺或不是承诺。
所以异步函数的调用者也需要等待。
顺便说一句,这里的一个答案说“如果你希望异步函数立即返回一个值,你可以使用 Promise.resolve”,这是错误返回等待的值会返回 Promise? (ES7 异步/等待)