我注意到async
关键字可以被分配任何值,甚至可以用作普通变量:
let async = "world";
console.log(async)
console.log("Hello " + async)
尽管如此,它仍然可以像以前一样继续运行:
let async = "world";
async function foo(input) {
return input;
}
let barPromise = foo("bar");
console.log("bar promise is:", typeof barPromise);
console.log("bar promise also has a .then:", typeof barPromise.then === "function");
barPromise
.then(output => console.log("bar promise returns:", output));
console.log("async is still assigned:", async);
foo("Hello ")
.then(output => console.log(output + async));
即使await
也在做同样的事情:
let await = "world";
console.log("await is:", await)
async function foo(input) {
return input;
}
async function bar(input) {
console.log("before");
let output = await foo(input);
console.log(output);
console.log("after");
}
bar("hello")
这是怎么回事?为什么关键字可用作变量?
答案 0 :(得分:8)
答案一开始令人困惑,但之后就会有意义
async
关键字。有一个async function
construct (MDN):link to the specs。因此async
仅在后跟函数时才具有特殊含义-作为表达式(传统函数和箭头函数)或声明。因此,称为async
的变量是有效的,因为后跟function
的变量在语法上无效。与语义没有冲突:
let foo;
//function declaration
foo function bar() {}; //SyntaxError
let foo;
//function expression
let bar = foo function() {}; //SyntaxError
await
,await
expression (MDN):link to the specs的一部分。语义要求await
后跟一元表达式,并且必须位于async
函数内部-某些语法仍然无法与其他变量有效。我没有任何消息来源,但是有理由得出这样的结论是为了保持向后兼容性。如果在ES5中有使用async
作为变量的代码,它稍后会突然中断。通过使async
仅在否则会出现SyntaxError的地方有效,可以确保旧代码和新代码可以共存。与await
相同。
有趣的是,await
的语义实际上导致了最初还是很奇怪的行为-您不能将其用作async
函数中的变量。要么声明它:
async function foo() {
let await = "world"; //SyntaxError - not a valid identifier here
}
不访问它:
let await = "world"; //valid identifier
async function foo() {
console.log(await); //SyntaxError - it is not followed by an expression
}
这在开始时也是令人困惑的,但是,向后兼容是有意义的。即使ES6之前的代码使用await
作为变量,也不会在async
函数中使用它,因为它们不存在。因此,旧代码有效,并且仍然没有冲突。