资讯专栏INFORMATION COLUMN

闲谈异步调用“扁平”化

Jaden / 3021人阅读

摘要:而的主线程中不允许操作网络,更是将程序员们推向了异步的深渊。异步深渊产生的主要原因是回调,这在里尤其严重。为了逃离回调的深渊,大家开始想各种办法来把回调扁平化。目前已经在等环境中得到支持,使用的不仅能大大简化代码,还能降低逻辑思路的复杂度。

哦,代码……就把它们当成插图吧

随着 CPU 从单核变多核,软件从注重功能到注重体验,Web 从页面跳转方式到 Web2.0 的无刷新加载(AJAX),程序员越来越多的接触多线程和异步。而 Android 的主线程中不允许操作网络,更是将程序员们推向了异步的深渊。异步深渊产生的主要原因是回调,这在 nodejs 里尤其严重。

// [node.js]

doFirstThing(function(err, data) {
    doSecondThing(data, function(err, data) {
        doThirdThing(data, function(err, data) {
            // ... fall down
        })
    });
});

为了逃离回调的深渊,大家开始想各种办法来把回调扁平化。

在 JavaScript 中,Promise(指该类方法而非某个库)成为众多解决方案的佼佼者,并成功被 ES6 采纳。

// [node.js]

doFirstThing()
    .then(doSecondThing)
    .then(doThirdThing)
    // .then(...) - continuous
    .catch(function() {
        // something wrong
    });

而 C# 则通过 Task 和 ThreadPool 让异步编程变得容易。前面谈论的 C# 并行计算(Parallel 和 ParallelQuery) 就是基于 Task 的。不过使用 Task.ContinueWith()Parallel.ForEach() 的时候,就会觉得:这不就是 Promise 吗?

// [csharp]

Task.Run(() => {
    // do first thing and return a data
    return "first";
}).ContinueWith(task => {
    // do second thing and return a data
    return new []{ task.Result, "second" };
}).ContinueWith(task => {
    // do final thing
    foreach (string s in task.Result) { Console.WriteLine(s); }
}).Wait();

之后 C#5.0 又推出 async/await 方案,将异步代码写得像同步代码一样,由编译器来将 async/await 代码封装成异步 Task 方式,而不是由人工处理,这大大降低了写异步程序的门槛。

// [csharp]

private async static Task Process() {
    string first = await Task.Run(() => "first");
    string[] all = await Task.Run(() => {
        return new [] { first, "second" };
    });
    
    await(Task.Run(() => {
        foreach (string s in all) { Console.WriteLine(s); }
    }));
}

JavaScript 程序员们一边在等着 ES7 的 async/await 特性,一边也没闲着,在 ES6 generator/yield 特性基础上开发了个 co 出来,提供了类似于 async/await 特性的异步编程方式。

// [node.js]

var co = require("co");

co(function*() {
    var first = yield new Promise(function(resolve) {
        setTimeout(function() {
            resolve("first");
        }, 100);
    });

    var all = yield new Promise(function(resolve) {
        setTimeout(function() {
            resolve([first, "second"])
        }, 200);
    })

    console.log(all);
});

// [ "first", "second" ]

不过 co 程序写起来又要写 Generator,又要用 yeild,还常常要封装 Promise,代码仍然不够简洁。目前 async/await 已经在 TypeScript、Babel、Node 7.6+ 等环境中得到支持,使用 JavaScript 的 async/await 不仅能大大简化代码,还能降低逻辑思路的复杂度。

2018.1.18 更新,因为 async/await 早已进入实践阶段

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/85974.html

相关文章

  • 从小小题目逐步走进 JavaScript 异步调用

    摘要:问题的主要目的是考察对异步调用执行结果的处理,既然是异步调用,那么不可能同步等待异步结果,结果一定是异步的经常用来模拟异步操作。 问题 原题来自 @若泽 的提问。 可修改下面的 aa() 函数,目的是在一秒后用 console.log() 输出 want-value function aa() { setTimeout(function() { return w...

    AprilJ 评论0 收藏0
  • 前后分离模型之封装 Api 调用

    摘要:和异步处理调用访问数据采用的方式,这是一个异步过程,异步过程最基本的处理方式是事件或回调,其实这两种处理方式实现原理差不多,都需要在调用异步过程的时候传入一个在异步过程结束的时候调用的接口。 Ajax 和异步处理 调用 API 访问数据采用的 Ajax 方式,这是一个异步过程,异步过程最基本的处理方式是事件或回调,其实这两种处理方式实现原理差不多,都需要在调用异步过程的时候传入一个在异...

    trilever 评论0 收藏0
  • 理解 JavaScript 的 async/await

    摘要:因为函数返回一个对象,所以可以用于等待一个函数的返回值这也可以说是在等函数,但要清楚,它等的实际是一个返回值。帮我们干了啥作个简单的比较上面已经说明了会将其后的函数函数表达式或的返回值封装成一个对象,而会等待这个完成,并将其的结果返回出来。 随着 Node 7 的发布,越来越多的人开始研究据说是异步编程终级解决方案的 async/await。我第一次看到这组关键字并不是在 JavaSc...

    tracymac7 评论0 收藏0
  • redux 闲谈

    摘要:使用中间件后的也是通过中间件包装后的。在的位置则进行触发监听器,监听器设置则在中增加。现在来解释,和对应关系我当时回答的是对应的函数名称,如果一致的话就会执行。呵呵,那个涂鸦大工程师有问题了如何绑定的呢,怎么确定是而不是。 redux 闲谈 起因: 在与涂鸦智能一个web工程师交流过程中,他询问我dispatch一个action,是如何和reducer 绑定的,dispatch(act...

    levius 评论0 收藏0

发表评论

0条评论

Jaden

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<