作为一个后端开发人员, 由于公司项目的需要. 最近开始转向javascript.
由于我司一向秉承TDD(测试驱动开发) 和100% 覆盖率的开发原则. 所以在做js 开发的时候, 免不了要对js 代码进行单元测试.
普通的js 代码还好, 但是遇到异步代码( 如timers.setTimeout(callback)). 由于我司项目的特殊性, 并不能引入第三方的测试框架. 而只能使用原生的js 方法和特性来进行单元测试. 也就是我们的单元测试框架和assert 库都是自己重写的.
最后发现老马的一篇文章 Testing Asynchronous JavaScript. 介绍了相关的方法.
总体的思路: mock 掉异步调用callback 的方法, 改为直接对callback 进行立即调用.
例如: 要对ajax 请求进行单元测试, 那么在测试文件中复写 $.ajax.
$.ajax = function(ajaxOpts) {
var doneCallback = ajaxOpts.done;
doneCallback(simulatedAjaxResponse);
};
然后,这篇文章推荐使用Promise 来代替callback 来编写异步方法. 作为一个后端人员, 又对Promise 进行了一番研究.
Promise
- 核心思想: 关注点从operation 的调用转移到处理operation 的结果.
1, Promise
- 方法的调用返回promise, 而不是操作的结果.
- promise 是一种代理, 代表操作的future result.
- Promise 是对in process 的异步操作的封装, 可以从方法返回, 传递给方法, 存储在queue 中.
- jquery 中的deffer 就属于promise, 这说明promise 解决的是一种带有延迟的事件, 这个事件会被延迟到未来某个合适点再执行.
- 执行过程: 在promise 上注册callback, 然后当操作完成且结果可用时, 由promise 执行callback.
2, Promise 与异步
- 同步方法的特性: return value && throw exception.
- Promise 给予异步方法了同步的2个特性. 它规定方法必须返回一个Promise.
- Promise 对象有三种状态:
- Pending – Promise对象的初始状态,等到任务的完成或者被拒绝;
- Fulfilled – 任务执行完成并且成功的状态;
- Rejected – 任务执行完成并且失败的状态
- Promise 的可选行为:
- 被一个值填充.
- 拒绝并附带exception.
- 这反映在then 方法接收的两个回调函数上.
3, Then
- then 不是为了将callbacks 连接到一个聚合集合.
- 而是在一个Promise 上应用transformation, 并从该转换中产生一个新的promise.
4, Immutable promise
- 方法必须返回一个新的promise. 这样将一个promise 分配给多个消费者时,它们的状态才不会互相干扰.
- 当promise 被fulfilled/failed 后,它就是immutable的.
- promise 的转换, 会有4种情况(2*2, 具体参照第2节Promise 的可选行为).
- 而Jquery 的promise 只是简单地将state mutate到寄存的promise 上.
- 当promise 被fulfilled/failed 后,它就是immutable的.
5, Exception
- 通过捕获异常并将其转换为rejection, 同时处理了
intentional(throw new Error("bad data"))/unintentional(aFunctionThatDoesNotExist())
异常.- 异常会冒泡到最近的rejection handler.
6, Promise 规范
- Promise 是含有then 方法属性的对象.
- 这样就能在完全不知promise 的实现的情况下, 编写库代码.