异步中 await 和 then 的区别,哪个更好 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
James369
V2EX    Flutter

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

  •  
  •   James369 2021-04-23 08:48:34 +08:00 5691 次点击
    这是一个创建于 1696 天前的主题,其中的信息可能已经有所发展或是发生改变。
    awit 虽然简洁。因为 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 的
    icanfork
        9
    icanfork  
       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 的时间内干别的去了
    这种说法很不准确,推荐你了解协程相关的内容
    shakaraka
        16
    shakaraka  
    PRO
       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     Solana     976 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 29ms UTC 17:55 PVG 01:55 LAX 09:55 JFK 12:55
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86