提问人:webbyweb 提问时间:4/22/2020 更新时间:4/22/2020 访问量:1042
async 标签是否用 Promise 包装 JavaScript 函数?
Does async tag wrap a JavaScript function with a Promise?
问:
所以我理解“异步”确保函数将返回一个 Promise,如果没有,那么它会将其包装在一个 promise 中。
我的问题是,如果函数已经返回一个 Promise,那么“异步”是否会将其包装在另一个 Promise 中?
async 函数,返回 non-Promise:
async function foo() {
return 5;
}
console.log(foo()) // Promise { 5 }
regular函数,返回Promise:
function foo() {
return Promise.resolve(5);
}
console.log(foo()) // Promise { 5 }
async 函数,返回 Promise:
async function foo() {
return Promise.resolve(5);
}
console.log(foo()) // Promise { <pending> }
为什么最后一个返回 “Promise { pending }” ?我的直觉告诉我,冗余的“异步”标签正在用另一个 Promise 包装已经返回的 Promise。这是正确的吗?
答:
您需要将最后一个函数调用为:
foo.then(function(r){console.log(r)});
原因是,异步函数需要返回一个 promise。在结果得到解决之前,promise 将记录为挂起状态。要获得承诺,您必须调用“then”。
以下是有关以下详细信息的链接:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
下面是有关异步 functinos 的详细信息的链接:Here is a link for more info about async functinos: https://fmpapidev.holstein.ca/swagger/index.html
评论
如果函数返回 Promise,则该函数返回的 Promise 将解析为与原始 Promise 相同的值。这可以通过一个简单的例子看出:async
async function foo() {
return Promise.resolve(42);
}
console.log(await foo()); // "42", not "Promise { 42 }"
因此,在大多数正常情况下,我们可以简单地想象,异步函数体中的代码返回的 Promise 是在没有触及的情况下返回的。但是,正如您偶然发现的那样,即使异步函数返回的 Promise 将解析为与代码返回的 Promise 相同的值,但实际的 Promise 对象不一定相同:
let p1;
async function foo() {
p1 = Promise.resolve(42);
return p1;
}
let p2 = foo();
console.log('p1 === p2 ?', p1 === p2); // "false" (!)
所以我们可以看到,函数调用返回的 Promise 对象实际上和函数体返回的 Promise 对象是不一样的。但是,无论如何,当我们(或使用)时,它都会给出相同的结果:await
Promise.then()
let p1;
async function foo() {
p1 = Promise.resolve(42);
return p1;
}
let p2 = foo();
console.log(await p1); // '42'
console.log(await p2); // also '42'
(请注意,要在节点 repl shell 中运行这些示例,您需要像这样包装它们:
async function main() {
/* code using async / await here */
}
main();
评论
现在我不确定 / 的原生实现对于现代节点应用程序是什么,但如果你看看它转译到节点 6 时会生成什么async
await
Babel
以这个简单的异步函数为例:
async function fooAsync() {
return 1;
}
Babel 将这段代码转换为如下所示:
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
function fooAsync() {
return _fooAsync.apply(this, arguments);
}
function _fooAsync() {
_fooAsync = _asyncToGenerator(function* () {
return 1;
});
return _fooAsync.apply(this, arguments);
}
您可以看到异步方法的转换及其生成的状态机。有趣的是,生成器在执行时会返回一个 .因此,要回答您的问题,只需在函数中包含关键字,就会使其返回 .这也可以从编译器发出呻吟的地方看出,如果你有一个方法,并且你没有指定返回类型new Promise()
async
Promise
Typescript
async
Promise<T>
评论