Javascript ES2017-异步vs.收益率
我对当前关于在下一个EcmaScript中添加异步函数和关键字Javascript ES2017-异步vs.收益率,javascript,ecmascript-6,async-await,ecmascript-2017,Javascript,Ecmascript 6,Async Await,Ecmascript 2017,我对当前关于在下一个EcmaScript中添加异步函数和关键字wait的讨论感到困惑 我不明白为什么在函数关键字之前必须有async关键字 在我看来,wait关键字用于等待生成器或承诺完成的结果,函数的返回应该足够了 await应能在正常函数和生成器函数中使用,无需额外的async标记 如果我需要创建一个函数,作为await的结果,它应该是可用的,那么我只需要使用一个promise 我问这个问题的原因是很好的解释,下面的例子来自哪里: async function setupNewUser(na
wait
的讨论感到困惑
我不明白为什么在函数
关键字之前必须有async
关键字
在我看来,wait
关键字用于等待生成器或承诺完成的结果,函数的返回应该足够了
await
应能在正常函数和生成器函数中使用,无需额外的async
标记
如果我需要创建一个函数,作为await
的结果,它应该是可用的,那么我只需要使用一个promise
我问这个问题的原因是很好的解释,下面的例子来自哪里:
async function setupNewUser(name) {
var invitations,
newUser = await createUser(name),
friends = await getFacebookFriends(name);
if (friends) {
invitations = await inviteFacebookFriends(friends);
}
// some more logic
}
如果函数的执行将等待完成孔函数,直到完成所有等待,则也可以作为正常函数执行
function setupNewUser(name) {
var invitations,
newUser = await createUser(name),
friends = await getFacebookFriends(name);
if (friends) {
invitations = await inviteFacebookFriends(friends);
}
// return because createUser() and getFacebookFriends() and maybe inviteFacebookFriends() finished their awaited result.
}
在我看来,整个函数的执行一直持续到下一个勾号(等待实现)完成为止。生成器函数的区别在于next()触发并更改对象的值和done字段。相反,函数在完成时会简单地返回结果,触发器是函数内部触发器,类似于while循环
我不明白为什么必须在function关键字之前加上async
关键字
出于同样的原因,我们在生成器函数之前有*
符号:它们将函数标记为非凡。在这方面,它们非常相似——它们添加了一个可视标记,该函数体不会自行运行完成,但可以与其他代码任意交错
*
表示一个生成器函数,它将始终返回一个生成器,该生成器可以通过使用类似于迭代器的方式从外部进行高级(和停止)
async
表示一个异步函数,它将始终返回一个依赖于其他承诺的承诺,并且其执行与其他异步操作并发(可能从外部取消)
确实,关键字并非严格必需的,函数的类型可以通过相应的关键字(yield(*)
/wait
)是否出现在其正文中来确定,但这将导致代码的可维护性降低:
- 不太容易理解,因为你需要扫描整个身体来确定类型
- 更容易出错,因为添加/删除这些关键字很容易破坏函数,而不会出现语法错误
正常功能,其执行将等待完成孔体,直到完成所有等待
这听起来像是您想要一个阻塞函数,它是一个并发设置中的函数。前面使用async关键字的原因很简单,因此您知道返回值将转换为承诺。如果没有关键字,解释器如何知道这样做。
我认为这是在C#中首次引入的,EcmaScript从TypeScript中获取了大量的东西。TypeScript和C#是安德斯·海尔斯伯格(andershejlsberg)构思的,两者类似。
假设您有一个函数(这个函数只是为了进行一些异步工作)
这个函数将使我们等待一个随机时间并返回一个Promise(如果您使用jquerypromise类似于Deferred)对象。要在今天使用此函数,您可以编写如下内容
function test(){
timeoutPromise().then(function(waited){
console.log('I waited' + waited);
});
}
async function test(){
var message = 'I waited' + (await timeoutPromise());
console.log(message);
return message;
}
这很好。现在让我们尝试返回日志消息
function test(){
return timeoutPromise().then(function(waited){
var message = 'I waited' + waited;
console.log(message);
return message; //this is where jQuery Deferred is different then a Promise and better in my opinion
});
}
这还不错,但是代码中有两个返回语句和一个函数
现在使用async时,它将如下所示
function test(){
timeoutPromise().then(function(waited){
console.log('I waited' + waited);
});
}
async function test(){
var message = 'I waited' + (await timeoutPromise());
console.log(message);
return message;
}
代码很短并且是内联的。如果你写了很多。然后()或。done()您知道代码有多不可读
现在为什么在函数前面加上async关键字。这表明你的返回值不是返回的值。理论上你可以写这篇文章(这可以用c完成,我不知道js是否允许,因为它还没有完成)
你看,你返回一个数字,但实际返回的是一个你不必使用的承诺
返回新承诺(函数(解析,拒绝){resolve(5);};
因为你不能等待一个数字,只有一个Promiseawait test(false)
会抛出一个异常,await test(true)
不会抛出异常,如果你不在前面指出async。通过将函数标记为async
,你告诉JS总是返回一个Promise
因为它总是会返回一个承诺,所以它也可以在自己的块内等待承诺。想象一下,它就像一个巨大的承诺链——函数内部发生的事情会有效地固定到它的内部。然后()
块,返回的是链中的最终。然后()
例如,此函数
async function test() {
return 'hello world';
}
…返回一个承诺。因此您可以像执行承诺一样执行它,。然后()
test().then(message => {
// message = 'hello world'
});
所以
大致类似于
function test() {
return getUser().then(function (user) {
return user.getReport().then(function (report) {
report.read = true;
return report;
});
});
}
在这两种情况下,传递给test().then()
的回调将作为其第一个参数接收report
生成器(即标记函数*
并使用产生关键字)是一个完全不同的概念。它们不使用承诺。它们有效地允许您在代码的不同部分之间“跳转”,从函数内部生成结果,然后跳回该点并继续进行下一个屈服块
尽管它们感觉有些相似(即“暂停”执行,直到其他地方发生某事),async/await
只会给你这种错觉,因为它扰乱了承诺执行的内部顺序。它实际上不是等待,而是在回调发生时洗牌
相比之下,生成器的实现方式不同,因此生成器可以维护状态并进行迭代
电话是
function test() {
return getUser().then(function (user) {
return user.getReport().then(function (report) {
report.read = true;
return report;
});
});
}
function await(x) {
return 'awaiting ' + x
}
function foo() {
return(await(42))
}