V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
James369
V2EX  ›  Flutter

异步中 await 和 then 的区别,哪个更好

  •  
  •   James369 · 2021-04-23 08:48:34 +08:00 · 5284 次点击
    这是一个创建于 1316 天前的主题,其中的信息可能已经有所发展或是发生改变。
    await 虽然简洁。因为 await 需要等待返回才继续向下执行,如果是较耗时的操作就得等待。


    方式一:
    await u = login();
    getUserInfo(u);
    otherTask(); // 必须等待 login()返回。


    方式二:
    login().then((u) {
    getUserInfo(u);
    );
    otherTask(); //可以并行

    我觉得 then 更加符合逻辑。
    第 1 条附言  ·  2021-04-23 10:13:18 +08:00
    同意楼下有位 V 友说的“要有更好的结构来使用 await”,对于 await 来说需根据具体场景谨慎使用。
    46 条回复    2021-04-30 07:42:03 +08:00
    IGJacklove
        1
    IGJacklove  
       2021-04-23 08:52:51 +08:00 via Android
    这有什么好比的。。。。那你要是十个异步你嵌套十个 then 吗?
    James369
        2
    James369  
    OP
       2021-04-23 08:54:53 +08:00
    @IGJacklove 嵌套总比使用不当好吧
    renmu123
        3
    renmu123  
       2021-04-23 08:55:47 +08:00 via Android   ❤️ 1
    u=login()
    othertask()
    await u
    getuserinfo ()

    js 是这样的
    dzdh
        4
    dzdh  
       2021-04-23 08:55:54 +08:00
    如果你 then 里面要做多步且必须要每一步需要前一个返回值呢。嵌套吗
    treblex
        5
    treblex  
       2021-04-23 08:57:40 +08:00   ❤️ 2
    如果下一步需要上一步的结果就用 await 转成同步,否则都直接 then

    ```dart
    var uid = await login().then((u) {
    return u.id
    );
    otherTask(uid);
    ```
    pabupa
        6
    pabupa  
       2021-04-23 08:57:42 +08:00 via Android
    await 是为了避免回调地狱的语法糖,他的实现方式也是回调。
    至于非阻塞的调用,你需要使用 wait 方法(传入多个 future )。
    ymcz852
        7
    ymcz852  
       2021-04-23 09:00:46 +08:00
    用 async/await 一样的,还美观点
    方式一:
    otherTask();
    await u = login();
    getUserInfo(u);
    free9fw
        8
    free9fw  
       2021-04-23 09:02:20 +08:00
    await 解决 callback hell 的
    belin520
        9
    belin520  
       2021-04-23 09:05:06 +08:00 via iPhone
    不知道从何说起,楼主还是继续用 promise 吧
    walpurgis
        10
    walpurgis  
       2021-04-23 09:06:38 +08:00 via Android   ❤️ 5
    await 外面再套一层 async 就行了

    (async()=>{
    await u = login();
    getUserInfo(u);
    })();
    otherTask();
    hereIsChen
        11
    hereIsChen  
       2021-04-23 09:08:59 +08:00   ❤️ 1
    这个看习惯,我都是混着用的,容易出问题的就用 then catch
    层数多的就用 await
    IGJacklove
        12
    IGJacklove  
       2021-04-23 09:10:09 +08:00 via Android
    感觉你刚学编程没多久的样子。。。
    whileFalse
        13
    whileFalse  
       2021-04-23 09:12:44 +08:00
    @walpurgis 你可真是个小机灵鬼
    yunyuyuan
        14
    yunyuyuan  
       2021-04-23 09:14:38 +08:00
    哈哈,居然有这种问题。
    单手拿手机好还是双手拿手机好?
    learningman
        15
    learningman  
       2021-04-23 09:23:31 +08:00 via Android
    await 其实不是等待,你可以理解为暂停的只有当前线程,CPU 在 await 的时间内干别的去了
    这种说法很不准确,推荐你了解协程相关的内容
    wunonglin
        16
    wunonglin  
       2021-04-23 09:24:12 +08:00
    rxjs 得永生
    lneoi
        17
    lneoi  
       2021-04-23 09:27:32 +08:00
    这不是哪个好的问题吧 如果这种不必等待的 本来就不能让他被卡住 使用 await 之前应该注意避免这种情况的
    cxe2v
        18
    cxe2v  
       2021-04-23 09:28:30 +08:00
    otherTask 不需要等待前面的结果的话,你把它放在 await 前面不就行了?
    rogi
        19
    rogi  
       2021-04-23 09:28:36 +08:00
    不喜欢 then 链,还是喜欢 async/await 这种写法,同步发送异步请求的方法楼上已经说了
    acmore
        20
    acmore  
       2021-04-23 09:44:05 +08:00
    “因为 await 需要等待返回才继续向下执行” 说明你还在用同步思维来异步编程。
    可以试着想一下程序不是 “向下” 执行的,而是多个单元同时执行的,相较于早早地完成下一步,所有单元整体上尽早完成才是更重要的。

    如果你的程序设计是让主线程卡在 await 上了,那么要么用 then,缺点是失去了上下文的同步控制;要么就重新整理一下 code,一定有更好的结构来使用 await.
    phony2r
        21
    phony2r  
       2021-04-23 09:56:21 +08:00
    我觉得你的理解有问题
    yaphets666
        22
    yaphets666  
       2021-04-23 10:23:33 +08:00
    js 吗 当然 then 好 async 和 await 的异常处理是业界难题 没有统一且玩美的方案
    um1ng
        23
    um1ng  
       2021-04-23 10:53:19 +08:00
    async/await yyds
    Niphor
        24
    Niphor  
       2021-04-23 11:02:19 +08:00
    方式一:
    otherTask();
    await x = login().then(getUserInfo);

    方式二:
    login().then(getUserInfo);
    otherTask(); //可以并行

    😈
    des
        25
    des  
       2021-04-23 11:13:12 +08:00
    // 不需要 then
    pLogin = login();
    otherTask();
    u = await pLogin;
    getUserInfo(u);
    lonelymarried
        26
    lonelymarried  
       2021-04-23 11:28:30 +08:00
    必须 await 啊,看起来都舒服些
    huijiewei
        27
    huijiewei  
       2021-04-23 11:36:07 +08:00
    @yaphets666

    ```
    export const flatry = <T, E>(promise: Promise<T>): Promise<{ data: T | undefined; error: E | undefined }> => {
    return promise.then((data) => ({ data, error: undefined })).catch((error) => ({ data: undefined, error }));
    };
    ```
    ALVC666
        28
    ALVC666  
       2021-04-23 11:57:25 +08:00
    两个其实都是一样的东西
    看你预期结果吧
    await 我觉得主要是异常处理的写法问题
    try catch 我觉得也很不美观
    charlie21
        29
    charlie21  
       2021-04-23 12:28:28 +08:00 via iPhone
    真是敢问敢答阿
    hoyixi
        30
    hoyixi  
       2021-04-23 12:37:25 +08:00   ❤️ 2
    你吐槽的 await 槽点,正是 await 诞生的原因,哈哈
    好比勺子是用来喝汤之类,用在筷子不方便的场合,而你吐槽:勺子竟然不能像筷子一样夹菜。
    yaphets666
        31
    yaphets666  
       2021-04-23 13:30:29 +08:00
    @huijiewei 没看太懂 意思 flatry 是一个函数 把 await xxxx 传进去转换成 promsie 返回?
    @ALVC666 try catch 有时候捕获不到 await 结果的错误
    component
        32
    component  
       2021-04-23 14:42:04 +08:00
    Promise.all Promise.race Promise.allSettled 你们是真不知道还是配合他演戏呢?
    MyouiSouth
        33
    MyouiSouth  
       2021-04-23 14:52:59 +08:00
    @component Promise 跑错片场了,这儿是 dart,应该是 Future.wait (狗头
    TomatoYuyuko
        34
    TomatoYuyuko  
       2021-04-23 15:12:47 +08:00
    await 最麻烦的地方是 reject 要用 try catch 捕获,处理起来有点麻烦,别的位置倒是用起来很顺手
    TomatoYuyuko
        35
    TomatoYuyuko  
       2021-04-23 15:25:04 +08:00
    最近在用 async/await 做接口封装遇到了 catch 的坑,最后用了一种不太好的办法处理
    // response 拦截
    // showStatus 是用来弹框提示状态码国际化标语的方法
    ...
    catch (err) {
    reject({ code: err.status, msg: showStatus(err.status), data: null })
    }

    //post 方法的拦截
    ...
    catch (err) {
    return new Promise(resolve => {
    resolve({
    code: -1,
    msg: '',
    data: null
    })
    })
    }
    // 具体接口封装
    ...
    if(res.code !== -1){
    ...
    强行 resolve,这样就避开了在 api 部分写太多 try catch 的问题
    应该有更好的解决方法。。
    ALVC666
        36
    ALVC666  
       2021-04-23 15:30:31 +08:00
    @TomatoYuyuko
    我是参考了这个
    https://blog.grossman.io/how-to-write-async-await-without-try-catch-blocks-in-javascript/

    import to from './to.js';

    async function asyncTask() {
    let err, user, savedTask;

    [err, user] = await to(UserModel.findById(1));
    if(!user) throw new CustomerError('No user found');

    [err, savedTask] = await to(TaskModel({userId: user.id, name: 'Demo Task'}));
    if(err) throw new CustomError('Error occurred while saving task');

    if(user.notificationsEnabled) {
    const [err] = await to(NotificationService.sendNotification(user.id, 'Task Created'));
    if (err) console.error('Just log the error and continue flow');
    }
    }
    TomatoYuyuko
        37
    TomatoYuyuko  
       2021-04-23 16:56:21 +08:00
    @ALVC666 懂了,确实是个方法,相当于封了一层 promise 处理 err...
    gledos
        38
    gledos  
       2021-04-23 17:20:54 +08:00
    test
    chengxy
        39
    chengxy  
       2021-04-23 17:36:16 +08:00
    @component #32 他们估计都不知道 Promise.all...
    leelz
        40
    leelz  
       2021-04-23 21:37:51 +08:00
    js 走错片场了。。
    tonyaiken
        41
    tonyaiken  
       2021-04-24 00:04:22 +08:00 via iPhone
    @IGJacklove 我们公司就是这样写的,嵌套很多层异步。
    IGJacklove
        42
    IGJacklove  
       2021-04-24 00:20:10 +08:00 via Android
    @tonyaiken 这代码能看。。。。不可能不用 await 只嵌套吧。
    tonyaiken
        43
    tonyaiken  
       2021-04-24 03:41:14 +08:00 via iPhone
    @IGJacklove 能看,可以分离出单独的方法。就变成方法嵌套方法。
    tonyaiken
        44
    tonyaiken  
       2021-04-24 03:45:41 +08:00 via iPhone
    @IGJacklove 这是我们公司开源的内部使用的异步框架 https://github.com/linkedin/parseq
    xiubin
        45
    xiubin  
       2021-04-24 12:05:44 +08:00
    笑死了。。一个苦逼 iOS er 一直等带能使用 await 。。。居然举这么个例子。。
    williamx
        46
    williamx  
       2021-04-30 07:42:03 +08:00 via Android   ❤️ 1
    使用的场景不同,很多时候就是要等上一条执行完了才执行下一条,有时候不需要等待只需要执行完的通知,那么就用 then,否则就是 await,有时侯不想每个都加 async 或者有些函数不能加,那只能用 then 。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2095 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 00:33 · PVG 08:33 · LAX 16:33 · JFK 19:33
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.