美文网首页程序员
coroutine, promise, async, await

coroutine, promise, async, await

作者: 正向反馈 | 来源:发表于2018-06-12 00:36 被阅读18次

    结论:promise, async, await 是不完全的抽象,coroutine更适合异步开发,解放心智负担。

    近来,nodejs, python的发展,有些看不大懂。
    nodejs由于其异步io的纯粹,在web服务器上的超高性能,获得了极大的关注和发展。
    其关键特性,异步处理这块上,是这样发展的

    callback 有回调地狱的问题
    promise 把回调树平展开来,代码更好阅读
    generator 真以同步写异步
    async,await 以同步的方式来书写异步的代码

    python由于GIL的存在,在多线程处理上是没有未来的。
    所以python的web服务器基本上走的都是多进程的路子。
    多线程也好,多进程也好,都是上个时代的处理方式,解决c10k都够呛
    梳理下python在web服务器上的发展:

    多进程 例如 uWSGI 服务器。 性能其实也够用了
    回调 例如tornado 没有很详细的了解, 知道性能很高,有回调地狱的问题
    greenlet 技术 不了解有什么常用的服务器或者web框架出来
    asyncio
    python3.5也引入了async,await

    总结一下

    总之,io上,只有两种模型:

    1. 同步io
    2. 异步io

    想拥有更高的性能,只有异步io可以解决。然后如下几个共识:

    1. 回调嵌套回调,真心不适合人写的,太乱
    2. promise只是展平了,看起来好点了,但是流程的流转,与异常的结合还是不好
    3. async, await只是promise的再包装,本质没变。babel对async,await的支持就是通过转化成promise来实现的

    coroutine

    之前看过一种说法,

    coroutine保留了lisp的续延特性的精华

    什么是coroutine

    coroutine 是由用户调度的调用栈,即轻量线程

    为什么说coroutine更适合异步开发,

    举个例子

    这是await版

    async function selectPizza() {
      const pizzaData = await getPizzaData()    // async call
      const chosenPizza = choosePizza()    // sync call
      await addPizzaToCart(chosenPizza)    // async call
    }
    
    async function selectDrink() {
      const drinkData = await getDrinkData()    // async call
      const chosenDrink = chooseDrink()    // sync call
      await addDrinkToCart(chosenDrink)    // async call
    }
    
    (async () => {
      const pizzaPromise = selectPizza()
      const drinkPromise = selectDrink()
      await pizzaPromise
      await drinkPromise
      orderItems()    // async call
    })()
    

    这是lua的coroutine版

    function selectPizza() 
      local pizzaData = getPizzaData()    // async call
      local chosenPizza = choosePizza()    // sync call
      addPizzaToCart(chosenPizza)    // async call
    end
    
     function selectDrink() 
      local drinkData = getDrinkData()    // async call
      local chosenDrink = chooseDrink()    // sync call
     addDrinkToCart(chosenDrink)    // async call
    end
    
    (function ()
      selectPizza()
      selectDrink()
      orderItems()    // async call
    end)()
    

    可以看到,coroutine可以做到跟同步多线程一样的写法

    再举个例子, 异步与map的结合

    这是await版

    var arr = [1, 2, 3, 4, 5];
    
    var results = await Promise.all(arr.map(async (item)  => {
        await callAsynchronousOperation(item);
        return item + 1;
    }));
    

    这是lua的coroutine版

    local arr = {1,2,3,4,5}
    local results = arr.map(function (item) 
        callAsynchronousOperation(item)
        return item + 1
    end)
    

    两者功能并不完全一样

    await版,写库函数的人,需要关心库函数是异步的,调用方也需要关心
    所调用的函数是异步的,要用await去等待,并且声明调用了await的函数要用async修饰。
    coroutine版可以做到真正的以同步的方式来写异步的代码。
    同时,coroutine可以真正自然地与try-catch异常处理结合,而await需要做更多的处理

    在人月神话中,就有提到,程序的主要复杂度是不可减的,
    人脑是无法巨细无遗地面对所有复杂度的。 所以程序架构的本质是管理并屏蔽复杂度
    面向对象的三大特征,封装继承多态中,最有用的是
    * 封装 屏蔽复杂度
    * 多态 归一化处理

    基于以上的认识,我们知道,coroutine真正的屏蔽了异步带来的复杂度和心智负担,这在实际开发中,帮助是巨大的。

    大火的golang,相较于它的竞争者,优势突出,突出在于它的goroutine(特殊的coroutine)

    推荐

    • openresty nginx、coroutine、 web服务器,中间件
    • skynet actor model、coroutine、 游戏服务器

    相关文章

      网友评论

        本文标题:coroutine, promise, async, await

        本文链接:https://www.haomeiwen.com/subject/vemkeftx.html