jquery.when方法解决的问题就类似于java中多线程的问题,js发起的多个ajax请求。
当我们前台需要同时发起多个ajax请求,并且所有ajax都成功返回后,才执行某个操作。
原始的方式是使用ajax嵌套,也就是在一个ajax的回调函数中发起另一个ajax,但是这样无疑影响效率且容易带来弊端(我之前这么用的时候总是出现以下奇怪的问题,到现在我也没明白什么原因)。而现在使用when方法能轻易的解决这个问题。下面用when方法实现一个简单的动态加载js的方法:
基础代码:
$.loadJs = function(urls, success, fail) { // 参数适配,可以支持string|Array类型的参数 urls = $.isArray(urls) ? urls : urls.split(/,|;|\s+/) var ajaxs = [] for(var i = 0, l = urls.length; i < l; i++) { ajaxs.push($.getScript(urls[i])) } $.when.apply(this, ajaxs).done(success).fail(fail) }
当然,上面的代码存在很多bug,比如js会重复加载问题,重复加载可能引起变量重复初始化从而导致错误发生,改进:
$.loadJs = function(urls, success, fail) { // 参数适配,可以支持string|Array类型的参数 urls = $.isArray(urls) ? urls : urls.split(/,|;|\s+/) var ajaxs = [] for(var i = 0, l = urls.length; i < l; i++) { if( !$("script[src='" + urls[i] + "']")[0] ) { ajaxs.push($.getScript(urls[i])) } } $.when.apply(this, ajaxs).done(success).fail(fail) }
这次,我们在push之前先判断js是否已经加载,是不是就万无一失了呢?不是。这段代码仍然有潜在风险。我们在不同的地方同时调用loadJs来加载同一个脚本,那么就会对同一个脚本发起两个ajax请求,还是会引起冲突,所以我们需要有一个请求池。
$.loadJs = function(urls, success, fail) { // 请求池 var cache = $.loadJS.cache = $.loadJS.cache || {} var getDeferred = function(url) { if( url in cache) return cache[url] return cache[ url ] = $.getScript( url ) } // 参数适配,可以支持string|Array类型的参数 urls = $.isArray(urls) ? urls : urls.split(/,|;|\s+/) var ajaxs = [] for(var i = 0, l = urls.length; i < l; i++) { if( !$("script[src='" + urls[i] + "']")[0] ) { ajaxs.push( getDeferred( urls[i] ) ) } } $.when.apply(this, ajaxs).done(success).fail(fail) }现在不管何时何地,调用loadJs来加载同一个url的脚本,就会获得同一个ajax延迟对象。
一个简单的动态加载插件就算完成了。
评论
你肿么看?