首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

浅谈如何降低 HTML5 的异步编程复杂度(2)

浅谈如何降低 HTML5 的异步编程复杂度(2)

非 Promise 方式Wind.js 介绍 是 IBM 高级咨询师 的 ,引用他的话来说,是希望通过 JavaScript 这门语言体现 F# 中“计算表达式”特性,来达到简化异步编码的目的。基于 Wind.js 实现本文第一个例子,代码如下:
清单 4.基于 Wind.js 实现本文第一个例子的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var asyncTask = eval(Wind.compile("async", function (idx) { // 运行“编译”后的代码', 得到句柄
    for (var i=0; i<5; i++) {
        $await(Wind.Async.sleep(2000)); // 等待2秒再继续执行
        var result = parseInt(Math.random() * 100, 10) % 2,
            time = (new Date()).getTime(),
            prefix = "Wind.js " + time + " " + i + ":";
        if (result == 0) {
            console.info(prefix + "got an even number");
        } else {
            console.info(prefix + "got an odd number");
        }
    }
}));
asyncTask().start(); // 开始运行异步任务




图 3.清单 4 中代码的运行结果由于使用了$await(Wind.Async.sleep(2000)) 这行代码,我们实现了每 2 秒获得一个奇数或者偶数。好奇的读者也许想知道 Wind.js 运行原理,简单的说,Wind.js 先对源代码进行词法分析、语法分析,然后动态生成新代码以实现异步编程。
需求实现
同样还是员工场景的那三个关键方法,我们将用到 Wind.js 的 Wind.Async.Task 类,将回调写法的代码封装起来,代码示例如下:
清单 5.从服务端获取员工列表数据的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Employee.all = function(opt) {
    var opt = opt || {local: true}, Task = Wind.Async.Task;
    if (opt.local === true) {
        throw new Error('not implemented!');
    } else {
        return Task.create(function(t) { // 创建 Wind.Async.Task实例, 封装必须使用回调方法的代码
            $.ajax({
                url: "/async/api/employee",
                dataType: "json"
            }).then(function(items) {
                var employees = [];
                $(items).each(function(idx, item) {
                    employees.push(new Employee(item))
                });
                t.complete("success", employees); // 操作成功
            }, function(err) {
                t.complete("failure", err); // 操作失败
            });
        });
    }
};




清单 6.实现模拟场景的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$(document).ready(function() {
    var employeeTask = eval(Wind.compile("async", function (idx) { // 生成句柄
        try {
            var employees = $await(Employee.all({local: false})); // 通过$await方法以便”编译”
            for (var i=0; i<employees.length; i++) {
                var employee = employees;
                if (employee.age >= 30) {
                    var employeeWithDetail =
                        $await(Employee.get(employee.id, {local: false}));
                    $await(employeeWithDetail.create({local: true}));
                } else {
                    $await(employee.create({local: true}));
                }
            }
        } catch(err) {
            console.error(err);
        }
         
    }));
    employeeTask().start();
});

});




从清单 6 的代码不难看出,这种代码风格已经看不到 JavaScript 中常用的回调写法,毫无疑问,开发者会更容易接受这种“顺序执行”编程体验。
JSDeferred 介绍 则是一款独立、简洁的异步执行类库,通过 next、loop、call、parallel 和 wait 等方法实现异步编程。依然是基于 JSDeferred 改写本文第一个例子,代码如下:
清单 7.基于 JSDeferred 实现本文第一个例子的代码
1
2
3
4
5
6
7
8
9
10
11
12
Deferred.define(); // 将JSDeferred的方法变成全局方法
loop(5, function (i) { // 顺序循环5次
    var result = parseInt(Math.random() * 100, 10) % 2,
        time = (new Date()).getTime(),
        prefix = "JSDeferred " + time + " " + i + ":";
    if (result == 0) {
        console.info(prefix + "got an even number");
    } else {
        console.info(prefix + "got an odd number");
    }
    return wait(2); // 等待2秒
});




图 4.清单 11 中代码的运行结果由于篇幅限制,下面只列出 JSDeferred 实现模拟场景的代码:
清单 8.实现模拟场景的代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$(document).ready(function() {
    Deferred.define();

    next(function () {
        return Employee.all({local: false}); // 当从远端获得所有员工数据时,才运行下一步
    }).
    next(function (employees) {
        return loop(employees.length, function(i) { // 顺序遍历员工
            var employee = employees;
            if (employee.age >= 30) {
                return Employee.get(employee.id, {local: false})
                       .next(function(employeeWithDetail) {
                           return employeeWithDetail.create({local: true});
                       }); // 从远端获取员工明细,保存到本地
            } else {
                return employee.create({local: true});
            }
        })
    }).
    error(function(err) {
        console.error(err); // 异常会导致异步过程中断,并被打印
    })
});




由此可见,在改善异步编程体验方面,已经是百花齐放的局面,对于其他改善异步编程体验的方式,本文不一一罗列,感兴趣的读者可自行了解。
返回列表