ES 中要用 await,上一层的函数都要是 async 的?

2019-01-02 14:25:02 +08:00
 cstome
async function A() {
    let someData = await B();
    
    return someData;
}

async function B() {
    let someData = await C();
    
    //Some logic code
    return someResult;
}

async function C() {
    return new Promise();
}

A();

上面实例的,只有 C 是异步的,B 在调用 C 同步执行的时候,B 必须是异步函数。而 A()在调用 B 时需要 B 通过 C 的返回经过 B 的某些计算,再返回给 A,因此调用 B 的时候也要是同步的。想要让 B 同步,A 就必须是异步函数。

这样的话岂不是想要用 await,上层所有函数都必须是异步函数?

7375 次点击
所在节点    JavaScript
48 条回复
janxin
2019-01-02 14:32:12 +08:00
当然不是,你还是可以用 promise 的那种写法,不需要 async 传染
oyosc
2019-01-02 14:38:20 +08:00
async 返回的就是一个 promise 对象,你也可以直接 then 来写
cstome
2019-01-02 14:42:38 +08:00
@janxin #1
@oyosc #2

我知道,但是这样似乎还是没法优雅的解决回调的问题。
janxin
2019-01-02 14:46:43 +08:00
@cstome promise 不就是为了解决回调提出来的方法么?
oyosc
2019-01-02 14:47:22 +08:00
@cstome 相对于回调地狱这种来说,已经很优雅了,更直观的表示,如果你是指完全的同步这种问题,那应该是没有...
lrz0lrz
2019-01-02 14:49:53 +08:00
是这样的,async 是用来指定 await 的范围,如果没有 async,js 就不知道哪些代码需要等待 await 执行完成。

另外楼主这个例子,a 依赖 b 的结果,b 的结果依赖 c 的结果,c 的结果依赖异步的结果,所以 a 依赖异步的结果,理应是异步的呀?
shintendo
2019-01-02 14:52:05 +08:00
你想要哪一层用 await,就在那一层用 async,与上一层无关,上一层仍然可以 promise
如果你想要每一层都 await,自然每一层都要 async
async/await 不过是语法糖,再牛逼也不能真的把异步变同步啊
sagaxu
2019-01-02 14:52:42 +08:00
await 只能出现在 async 函数內,但是普通函数可以调用 async 函数
geelaw
2019-01-02 14:53:22 +08:00
async 的作用是启用该 context 内的自动 CPS 变换(也就是同步风格代码翻译成异步),await 的作用是表明这里是一个 CPS 变换的 checkpoint。

用同步的风格写异步的代码 = 用 await,从而包裹之的 function 必须用 async 修饰(也就是“启用 await ”)。

ES 的 async/await 和 C# 的一样。
CloudnuY
2019-01-02 14:54:15 +08:00
你让一个人帮你去楼下买东西,你必须在楼上等着他买回来,总不能自己出去逛街吧……
autoxbc
2019-01-02 14:57:11 +08:00
async 传染的本质:对于末端是异步的函数,在整个调用链上,从分界点(同步函数以同步形式调用异步函数)开始,到末端,要全部显式声明 async
a -> b -> c(以同步形式调用 d) -> d(异步) -> e(异步) -> f(异步)
d,e,f 必须是 async ; a,b,c 完全不需要

到底哪一层需要是异步函数,取决于程序到底可以在哪个位置并行,必然存在这么个分界点
cstome
2019-01-02 15:00:10 +08:00
@janxin #4
@oyosc #5

仔细想了一下,你们所说的改成 Promise 是怎么改?

能拿我的例子改一下吗?

改成这样?

```
function A() {
let someData = B().then(res => {
return res;
})
}

function B() {
let someData = C().then(res => {
//Some logic code
return someResult;
})
}

async function C() {
return new Promise();
}

A();
```
wyz123723
2019-01-02 15:01:36 +08:00
看你是想写成异步还是同步了。想写成同步,也就是下一句必须等待上一句执行完毕才能执行,那就得用 await,也就必须用 async。如果你想写成异步,那就写成 then 的形式,也就不需要加 async 了。
cstome
2019-01-02 15:03:46 +08:00
@autoxbc #11 此时 c 要怎样用同步的方式调用异步?

如果用 await 的话显然不行。
zbinlin
2019-01-02 15:06:15 +08:00
@cstome

async function A() {
return B();
}

async function B() {
let someData = await C();

//Some logic code
return someResult;
}

async function C() {
return new Promise();
}

A().then(..., ...);
cstome
2019-01-02 15:08:18 +08:00
@zbinlin #15 这样岂不是还是每一层都用 async
zbinlin
2019-01-02 15:11:38 +08:00
@cstome

function A() {
return B();
}

async function B() {
let someData = await C();

//Some logic code
return someResult;
}

function C() {
return new Promise();
}

A().then(..., ...)
cstome
2019-01-02 15:12:05 +08:00
@wyz123723 #13 我就是想要同步的。

比方说我用 axios 请求数据,必须根据请求结果才能进行判断,执行下一步。

如果用 Promise 方法就只能一直 then 下去,感觉整个程序都是写在 then 里,不优雅。

然而用了 async/await 发现这个问题。
zbinlin
2019-01-02 15:13:02 +08:00
@zbinlin 只要函数内有 await 才必须使用 async 定义
wyz123723
2019-01-02 15:19:59 +08:00

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/523102

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX