JavaScript 异步调用框架 (Part 2 - 用例设计)

 更新时间:2009年08月03日 23:53:28   作者:  
在上一篇文章里说到,我们要设计一个异步调用框架,最好能够统一同步异步调用的接口,同时具体调用顺序与实现方式无关。那么我们现在就来设计这样一个框架的用例。
传递回调
我们首先要考虑的一个问题是,如何传递回调入口。在最传统的XHR调用当中,回调函数会被作为最后一个参数传递给异步函数:
复制代码 代码如下:

function asyncOperation(argument, callback)

在参数相当多的时候,我们可以把参数放到一个JSON里面,这样参数就如同具名参数一样,可以通过参数名选择性的传递参数,不传递的参数相当于使用默认值。这是从Prototype开始就流行起来的做法:
复制代码 代码如下:

function asyncOperation(argument, options)

然而这两种做法都有一个坏处,就是把同步函数改为异步函数(或同步异步混合函数)时,必须显式地修改函数签名,在最后增加一个(或多个)参数。

由于在调用栈的底层引入异步函数对我们来说太常见了,为此可能要更改一大堆上层调用函数签名的成本实在是太高了,所以我们还是想一个不用修改函数签名的做法吧。

在这里我参考了.NET Framework的IAsyncResult设计,把异步操作有关的一切信息集中到一个对象上来,从而避免了对函数签名的修改。在此,我们假设一个异步函数的调用原型是这样子的:
复制代码 代码如下:

function asyncOperation(argument) {
operation = new Async.Operation();
setTimeout(function() { operation.yield("hello world"); }, 1000);
return operation;
}

在这段代码里,我们返回了一个Operation对象,用于将来传递回调函数。同时,我们通过setTimeout模拟了异步返回结果,而具体的返回方式就是yield方法。

接着,我们还要设计传递回调函数的方法。由于我们不能好像C#那样重载+=运算符,所以只能用函数传递回调函数:
复制代码 代码如下:

var operation = asyncOperation(argument);
operation.addCallback(function(result) { alert(result); });

在C#里面做这样的设计是不安全的,因为在异步操作可能在添加回调之前就完成了。但在JavaScript里面这样写是安全的,因为JavaScript是单线程的,紧接着asyncOperation的同步addCallback必然先执行,asyncOperation中的异步yield必然后执行。

调用顺序
可能有人要问,如果用户使用同步的方式来调用yield,这时候执行顺序不一样依赖于yield的实现吗?没错,不过yeild是在框架中一次性实现的,我们只要把它做成异步的就可以了,这样即使对它进行同步调用,也不影响执行顺序:
复制代码 代码如下:

function psudoAsyncOperation(argument) {
operation = new Async.Operation();
operation.yield("hello world");
return operation;
}
var operation = asyncOperation(argument);
operation.addCallback(function(result) { alert(result); });

就算把代码写成这个样子,我们也能确保addCallback先于yield的实际逻辑执行。

事后回调
有时候,框架的使用者可能真的写出了先yield后addCallback的代码。这时候,我认为必须保证addCallback中添加的回调函数会被立即触发。因为用户添加这个回调函数,意味着他期望当异步操作有结果时通知这个回调函数,而这与添加回调函数时异步操作是否完成无关。为此,我们再添加一个用例:
复制代码 代码如下:

function psudoAsyncOperation(argument) {
operation = new Async.Operation();
operation.yield("hello world");
return operation;
}
var operation = asyncOperation(argument);
setTimeout(function() {
operation.addCallback(function(result) { alert(result); });
}, 1000);

小结
到这里,我们就设计好了一个名为Async.Operation的异步操作对象,具体如何实现关键的yield方法和addCallback方法将在下一篇文章讲述如果。

相关文章

  • 解决layui表格内文本超出隐藏的问题

    解决layui表格内文本超出隐藏的问题

    今天小编就为大家分享一篇解决layui表格内文本超出隐藏的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-09-09
  • Webwork 实现文件上传下载代码详解

    Webwork 实现文件上传下载代码详解

    WebWork 当然也提供了很友好的拦截器来实现对文件的上传,让我们可以专注与业务逻辑的设计和实现,在实现上传和下载时顺便关注了下框架上传下载的实现
    2016-02-02
  • bootstrapValidator表单验证插件学习

    bootstrapValidator表单验证插件学习

    这篇文章主要为大家详细介绍了表单验证插件bootstrapValidator的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12
  • JavaScript实现各种排序的代码详解

    JavaScript实现各种排序的代码详解

    这篇文章给大家介绍了js实现各种排序功能,包括冒泡排序,选择排序和插入排序,代码简单易懂,非常不错,具有参考借鉴价值,需要的的朋友参考下吧
    2017-08-08
  • 提高Web性能的前端优化技巧总结

    提高Web性能的前端优化技巧总结

    这篇文章讲述可以帮助 改善优化前端的技术,非常有用。主要内容有清理代码、压缩图片、压缩外部资源、使用CDN,以及一些其它方法。这些方法会为你的网站带显著的速度提升和整体性能提升。下面跟着小编一起来看下吧
    2017-02-02
  • 探索JavaScript函数的无限可能(函数基本概念)

    探索JavaScript函数的无限可能(函数基本概念)

    JavaScript中的函数是一种重要的编程概念,它允许我们封装可重用的代码块,并在需要时进行调用,本文将深入介绍JavaScript函数的各个方面,包括函数定义和调用、参数和返回值、作用域和闭包、高阶函数以及常见的函数应用场景,感兴趣的朋友一起看看吧
    2023-08-08
  • js实现GIF图片的分解和合成

    js实现GIF图片的分解和合成

    这篇文章主要为大家详细介绍了js实现GIF图片的分解和合成,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-10-10
  • JavaScript面向对象编写购物车功能

    JavaScript面向对象编写购物车功能

    这篇文章主要为大家详细介绍了JavaScript面向对象编写购物车功能的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-08-08
  • js观察者模式的介绍及使用

    js观察者模式的介绍及使用

    这篇文章主要介绍了java设计模式中观察者模式,全文通过举例子及代码的形式进行了一个简单的介绍,希望大家能够理解并且学习到其中知识
    2021-08-08
  • JS把内容动态插入到DIV的实现方法

    JS把内容动态插入到DIV的实现方法

    下面小编就为大家带来一篇JS把内容动态插入到DIV的实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-07-07

最新评论