在异步机制这章我们详细的分析了 deferred 的设计,其中提供了 deferred.promise 方法就是把普通对象转化成 deferred 对象了,ajax 就是把 deferred 对象给掺进去可以让整个 Ajax 方法变成了一个 deferred 对象,在Ajax方法中返回的是 jqXHR 一个包装对象,在这个对象里面混入了所有实现方法。
ajax: function(url, options) { var jqXHR = {} //ajax对象 deferred = jQuery.Deferred() //转成deferred对象 deferred.promise(jqXHR).complete = completeDeferred.add return jqXHR }
jQuery.ajax 的版本迭代:
为了向后兼容 XMLHttpRequest ,jqXHR 对象将公开下列属性和方法:
readyState status statusText responseXML and/or responseText 当底层的请求分别作出XML和/或文本响应 setRequestHeader(name, value) 从标准出发,通过替换旧的值为新的值,而不是替换的新值到旧值 getAllResponseHeaders() getResponseHeader() abort()
为了实现以上这些功能,jQuery 在对 jqXHR 做2个处理:
// Deferreds deferred = jQuery.Deferred(), //所有的回调队列,不管任何时候增加的回调保证只触发一次 completeDeferred = jQuery.Callbacks("once memory"),
给 jqXHR 扩充添加 promise 的属性和方法,然后添加 complete 方法,这里用的是回调列表的 add 方法(即添加回调)
deferred.promise(jqXHR).complete = completeDeferred.add;
此时的 jqXHR 就具有了 promise 的一些特性了与 callback 的回调列队了,当然这里有个重点,返回了一个只读的 deferred 对象,如果返回完整的 deferred 对象,那么外部程序就能随意的触发 deferred 对象的回调函数,很有可能在 AJAX 请求结束前就触发了回调函数(resolve),这就是与 AJAX 本身的逻辑相违背了。所以为了避免不经意间改变任务的内部流程,我们应该只返回 deferred 的只读版本 deferred.promise(),然后把对应的 done 与 fail 改成别名 success 与 error。
jqXHR.success = jqXHR.done; jqXHR.error = jqXHR.fail
我们还需要把用户自定的内部回调函数给注册到 jqXHR 对象上。
// 增加回调队列 for (i in { success : 1, error : 1, complete : 1 }) { /** * 把参数的回调函数注册到内部jqXHR对象上,实现统一调用 * 给ajax对象注册 回调函数add * deferred返回complete,error外部捕获 */ jqXHR[i](s[i]); }
通过一个 for 循环把对应的方法都执行了,具体就是这几个:
我们参考右边 Ajax 的模拟实现代码。
请验证,完成请求
由于请求次数过多,请先验证,完成再次请求
打开微信扫码自动绑定
绑定后可得到
使用 Ctrl+D 可将课程添加到书签
举报