-
jQuery的异步设计逻辑也确实很复杂,需要思维跳转很活跃,某一个时间在这里,下一个片段又要另一个地方去了,不是按照同步代码这样执行的。需要大家有一定的空间跳跃力了。
查看全部 -
when方法的设计。我们通过模拟的代码,可以很简单的分析整个流程:
1. 传递了多个异步对象,然后遍历每个异步对象给每一个对象绑定done、fail、progess方法,无非就是监听每一个异步的状态(成功,失败),如果是完成了自然会激活done方法。
2. updateFunc是监听方法,通过判断异步对象执行的次数来决定是不是已经完成了所有的处理或者是失败处理
3. 因为when也要形成异步操作,比如when().done(),所以内部必须新建一个jQuery.Deferred()对象,用来给后面链式调用。
4. 此刻监听所有异步对象(d1,d2...)的updateFunc的处理都完毕了,会给一个正确的通知给when后面的done方法,因为done是通过第三步jQuery.Deferred()创建的,所以此时就需要发送消息到这个上面,即:
deferred.resolveWith(contexts, values);
5. 内部的jQuery.Deferred()因为外部绑定了when().done(),所以done自然就收到了updateFunc给的消息了,可以继续之后的操作了。
查看全部 -
Deferred的then处理:
我们可以把每一次的then操作,当做是创建一个新的deferred对象,那么每一个对象都够保存自己的状态与各自的处理方法。通过一个办法把所有的对象操作都串联起来,这就是then或者pipe管道设计的核心思路了。
其实在内部创建了一个新的Deferred对象,不过这里的不同是通过传递一个回调函数,参数是newDefer,其实Deferred内部就是为了改变下上下文this为deferred,然后传递deferred给这个回调函数了,所以newDefer就指向内部的deferred对象了。
如果then返回的是一个promise对象(ajax)的时候,也可以直接处理了
if (returned && jQuery.isFunction(returned.promise)) { returned.promise() .done(newDefer.resolve) .fail(newDefer.reject) .progress(newDefer.notify);
查看全部 -
Deferred源码剖析
Deferred自身则围绕这三组数据进行更高层次的抽象
1、触发回调函数列表执行(函数名)
2、添加回调函数(函数名)
3、回调函数列表(jQuery.Callbacks对象)
4、Deferred最终状态(第三组数据除外)
var tuples = [ // action, add listener, listener list, final state ["resolve", "done", jQuery.Callbacks("once memory"), "resolved"], ["reject", "fail", jQuery.Callbacks("once memory"), "rejected"], ["notify", "progress", jQuery.Callbacks("memory")] ]
通过stateString有值这个条件,预先向doneList,failList中的list添加三个回调函数,分别是:
doneList : [changeState, failList.disable, processList.lock] failList : [changeState, doneList.disable, processList.lock]
1、changeState 改变状态的匿名函数,deferred的状态,分为三种:pending(初始状态), resolved(解决状态), rejected(拒绝状态);
2、不论deferred对象最终是resolve(还是reject),在首先改变对象状态之后,都会disable另一个函数列表failList(或者doneList);
3、然后lock processList保持其状态,最后执行剩下的之前done(或者fail)进来的回调函数。
4、所以第一步最终都是围绕这add方法:done/fail/是list.add也就是callbacks.add,将回调函数存入回调对象中。
查看全部 -
没有使用promise的情况下,实现了类似promise的功能,666!
查看全部 -
观察者模式中的订阅方法:
Done (操作完成)
Fail (操作失败)
Progress (操作进行中观察中模式中的发布方法:
resolve(解决)
reject(拒绝)
notify(通知)而且还提供了可以定义运行时的this对象的fire,fireWith,所以扩展了3个可以定义上下文的的接口:
resolveWith
rejectWith
notifyWith查看全部 -
“管道”风格
CommonJS Promise/A 标准这样定义的,promise对象上的then方法负责添加针对已完成和拒绝状态下的处理函数。then方法会返回另一个promise对象,这样可以形成“管道”风格。
查看全部 -
promise背后的思想:不是执行一个方法,然后阻塞应用程序等待结果返回,而是返回一个promise对象来满足未来值,即承诺、许诺完成当前操作后,会执行预先设定的后续操作
查看全部 -
querySelector的IE8兼容处理:在上下文调用的context元素上指定一个id,通过这个限制范围,这个方法用的非常广泛
具体过程:
1、关键是给context设置一个id,所以上下文content,就会存在这个id限制范围
2、拼接出查询的选择器,附上这个ID前缀
newSelector: "[id='sizzle-1405486760710'] div[class='text']"
3、查询
newContext.querySelectorAll( newSelector )
4、因为强制加了ID,所以需要删除
context.removeAttribute("id");
查看全部 -
正则表达式中【$&】的意思
$1、$2、...、$99 与 regexp 中的第 1 到第 99 个子表达式相匹配的文本。
$& 与 regexp 相匹配的子串。
$` 位于匹配子串左侧的文本。
$' 位于匹配子串右侧的文本。
$$ 直接量符号。
查看全部 -
document.querySelectorAll 与 element.querySelectorAll区别:
1、element.querySelectorAll 在文档内找全部符合选择器描述的节点包括Element本身
2、选择上下文是在aaRoot里面,选择器是.aaron就父节点,理论是找不到对应的节点的。但是结果跟document调用如出一辙,所以此时node ele类似document了。
3、可能的查找机制是这样的:首先在document的范围内进行查找所有满足选择器条件的元素,在上面这段代码中,我们的选择器是.aaron span,就是所有的直接父元素类名为.aaron的元素。然后,再看哪些元素是调用querySelector/querySelectorAll的元素的子元素,这些元素将会被返回。
查看全部 -
IE兼容问题:
1、关于getElementById,在IE8之前是不区分大小写的。除此之外,IE8之前在针对表单的处理时候,表单的name与id重名,并且name在id之前,则会返回表单元素
2、关于getElementsByTagName,如果选择器是通配符"*"的话,IE6-8会混杂注释节点,所以针对如果是tag为*的情况,我们需要做一个兼容的处理
3、关于getElementsByClassName,IE却并不支持这个方法,我们不得不专门为IE实现这么一个函数
查看全部 -
为什么排版引擎解析 CSS 选择器时一定要从右往左析?
1、要知道DOM树是一个什么样的结构,一个元素可能有若干子元素,如果每一个都去判断一下显然性能太差。而一个子元素只有一个父元素,所以找起来非常方便。你可以看看CSS的选择器的设计,完全是为了优化从子元素找父元素而决定的。
2、打个比如 p span.showing。你认为从一个p元素下面找到所有的span元素并判断是否有class showing快,还是找到所有的span元素判断是否有class showing并且包括一个p父元素快 ?
查看全部 -
CSS选择器分类:
群组选择器:逗号“,”
简单选择器:ID、标签、类、属性、通配符
关系选择器:孩子、后代、相邻、兄弟
伪类选择器:动作伪类、目标伪类、语言伪类、状态伪类、结构伪类、取反伪类伪类细分:
基本筛选器: eq get first lang It not odd root...
内容筛选器: contains empty has parent...
可见筛选器: hidden visible
子元素筛选器: first-child nth-child only-child...
表单: bottom checkbox foucs input text...查看全部 -
Deferred 提供了一个抽象的非阻塞的解决方案(如异步请求的响应),它创建一个promise对象,其目的是在未来某个时间点返回一个响应。简单来说就是一个异步/同步回调函数的处理方案。
一:Ajax的改造
$.ajax({ url: "aaron.html", success: function(){ alert("成功!"); }, error:function(){ alert("失败!"); } }) $.ajax("aaron.html") // 返回不再是xhr对象,而是经过包装的Deferred对象 .done(function(){ alert("成功"); }) .fail(function(){ alert("出错"); });
二:提供一种方法来执行一个或多个对象的回调函数
$.when($.ajax("a1.html"), $.ajax("a2.html")) .done(function(){ alert('2次回调都正确返回了') }) .fail(function(){ alert('出错了'); });
三:可以混入任意的对象接口中
jQuery的Deferred最好用的地方,就是模块化程度非常高,可以任意配合使用:
把需要处理的异步操作,用Deferred对象给包装一下,然后通过when方法收集异步的操作
function task(name) { var dtd = $.Deferred(); setTimeout(function() { dtd.resolve(name) }, 1000) return dtd; } $.when(task('任务一'), task('任务二')).done(function() { alert('成功') })
查看全部
举报