V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
James369
V2EX  ›  Flutter

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

  •  
  •   James369 · Apr 23, 2021 · 5901 views
    This topic created in 1843 days ago, the information mentioned may be changed or developed.
    await 虽然简洁。因为 await 需要等待返回才继续向下执行,如果是较耗时的操作就得等待。


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


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

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

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

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

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

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

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

    😈
    des
        25
    des  
       Apr 23, 2021
    // 不需要 then
    pLogin = login();
    otherTask();
    u = await pLogin;
    getUserInfo(u);
    lonelymarried
        26
    lonelymarried  
       Apr 23, 2021
    必须 await 啊,看起来都舒服些
    huijiewei
        27
    huijiewei  
       Apr 23, 2021
    @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  
       Apr 23, 2021
    两个其实都是一样的东西
    看你预期结果吧
    await 我觉得主要是异常处理的写法问题
    try catch 我觉得也很不美观
    charlie21
        29
    charlie21  
       Apr 23, 2021 via iPhone
    真是敢问敢答阿
    hoyixi
        30
    hoyixi  
       Apr 23, 2021   ❤️ 2
    你吐槽的 await 槽点,正是 await 诞生的原因,哈哈
    好比勺子是用来喝汤之类,用在筷子不方便的场合,而你吐槽:勺子竟然不能像筷子一样夹菜。
    yaphets666
        31
    yaphets666  
       Apr 23, 2021
    @huijiewei 没看太懂 意思 flatry 是一个函数 把 await xxxx 传进去转换成 promsie 返回?
    @ALVC666 try catch 有时候捕获不到 await 结果的错误
    component
        32
    component  
       Apr 23, 2021
    Promise.all Promise.race Promise.allSettled 你们是真不知道还是配合他演戏呢?
    MyouiSouth
        33
    MyouiSouth  
       Apr 23, 2021
    @component Promise 跑错片场了,这儿是 dart,应该是 Future.wait (狗头
    TomatoYuyuko
        34
    TomatoYuyuko  
       Apr 23, 2021
    await 最麻烦的地方是 reject 要用 try catch 捕获,处理起来有点麻烦,别的位置倒是用起来很顺手
    TomatoYuyuko
        35
    TomatoYuyuko  
       Apr 23, 2021
    最近在用 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  
       Apr 23, 2021
    @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  
       Apr 23, 2021
    @ALVC666 懂了,确实是个方法,相当于封了一层 promise 处理 err...
    gledos
        38
    gledos  
       Apr 23, 2021
    test
    chengxy
        39
    chengxy  
       Apr 23, 2021
    @component #32 他们估计都不知道 Promise.all...
    leelz
        40
    leelz  
       Apr 23, 2021
    js 走错片场了。。
    tonyaiken
        41
    tonyaiken  
       Apr 24, 2021 via iPhone
    @IGJacklove 我们公司就是这样写的,嵌套很多层异步。
    IGJacklove
        42
    IGJacklove  
       Apr 24, 2021 via Android
    @tonyaiken 这代码能看。。。。不可能不用 await 只嵌套吧。
    tonyaiken
        43
    tonyaiken  
       Apr 24, 2021 via iPhone
    @IGJacklove 能看,可以分离出单独的方法。就变成方法嵌套方法。
    tonyaiken
        44
    tonyaiken  
       Apr 24, 2021 via iPhone
    @IGJacklove 这是我们公司开源的内部使用的异步框架 https://github.com/linkedin/parseq
    xiubin
        45
    xiubin  
       Apr 24, 2021
    笑死了。。一个苦逼 iOS er 一直等带能使用 await 。。。居然举这么个例子。。
    williamx
        46
    williamx  
       Apr 30, 2021 via Android   ❤️ 1
    使用的场景不同,很多时候就是要等上一条执行完了才执行下一条,有时候不需要等待只需要执行完的通知,那么就用 then,否则就是 await,有时侯不想每个都加 async 或者有些函数不能加,那只能用 then 。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   1075 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 117ms · UTC 23:12 · PVG 07:12 · LAX 16:12 · JFK 19:12
    ♥ Do have faith in what you're doing.