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,上层所有函数都必须是异步函数?

7575 次点击
所在节点    JavaScript
48 条回复
jjx
2019-01-03 08:16:06 +08:00
@kcats

deno 有一个目标也是这个

await 传染很容易出 bug, 不过大都可以在测试层面解决掉
DOLLOR
2019-01-03 08:33:56 +08:00
callback, Promise, async function 都有传染性,只是语法糖甜度不同,该异步的仍要异步
abc635073826
2019-01-03 15:12:02 +08:00
@cstome 本质上东西回来了你是要拿到的,它总有一个归属地
kcats
2019-01-03 15:16:08 +08:00
@jjx 这是正常的吧, 一个异步的函数在外部还能搞成同步的? 那异步的作用有啥意义? 楼主的问题是自己没想清楚, top level await 解决的问题是在没有 async 函数标记的情况下同步写异步代码, 和楼主的问题是两码事.
cstome
2019-01-03 15:36:39 +08:00
@kcats #44 其实我就是想把异步的强制变同步。

说实话,在大部分编程中,同步的情况比异步要多。

只不过 JS 是动不动都是异步的。。。
kcats
2019-01-03 16:24:03 +08:00
@cstome 这个只是语法(内部处理机制)上的不同. 之前有和一个做 cdn 的哥们讨论过, 他习惯于写 go 和 lua, 这两个语言都有 routine 的概念, io 操作都是异步的, 但是都是同步的写法. 这和 js 就是两个极端. js 本质上暴露给用户的就是一个纯异步的环境, async/await 只是一个语法糖, 把回调变成的同步的写法. 但是本质是没有变的. 因为 js 的函数栈与事件循环机制, 决定了只有一个调用栈被清空了之后, 才能够执行下一个事务. async/await 本质上还是回调, 相当于是把后续的代码分块了, 和 python 的 event 有点类似. 说白了 async/await 就是提供了一个标记, 既是给开发人员看的, 也是给解释器看的. 如果没有这个标记还要实现相同的效果, 那整个 js 的机制和 API 规范都要改了.
Sapp
2019-01-24 10:17:52 +08:00
同步如何能拿到异步的返回值?要么回调,要么把异步转为同步啊... 你的 b 一旦调用了 c,他就是个异步了,a 调用 b 也成了异步,你想拿到 a 返回的值,必然要么回调,要么把 a 转同步
libook
2019-01-29 15:53:41 +08:00
因为 A 必须依赖 B 执行完才可以继续执行,同时 B 也依赖 C 执行完才能继续执行,所以不管你用 callback 还是 Promise 还是 async,都逃不掉三者都做同步化处理:

callback 版本:

function A(resultFromB) {
let someData = resultFromB;
return someResult;
}

function B(resultFromC, cb) {
let someData = resultFromC;

//Some logic code
cb(someResult);
}

function C(cb) {
(new Promise()).then((result) => {
cb(result, A);
});
}

C(B);

Promise 版本:

function A(resultFromA) {
let someData = resultFromA;

return someData;
}

function B(resutlFromC) {
let someData = resutlFromC;

//Some logic code
return someResult;
}

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

C.then(B).then(A).then((resultFromA) => {
//Do something.
});

避免不了的,但是外层层都用 async 不是因为内层用了 async,而是因为外层关心内层执行完的结果,如果不关心的话完全可以不用 async。

function B() {
new Promise();
}

function A() {
B();//我不关心 B 执行完返回啥,就让他自生自灭吧
//继续执行其他的代码
}

A();

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

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

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

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

© 2021 V2EX