为什么下划线推迟修复我的许多问题?

ces*_*ara 48 javascript backbone.js underscore.js

在使用主干几周后,我意识到下划线延迟最终修复了我遇到的关于渲染各种视图的许多异步问题.有人可以请帮助我准确理解下划线延迟的作用以及$ .ready()或其他类型的等待dom来呈现函数的方式有何不同.使用它有什么不利之处?

_.defer = function(func) {
    return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
};
Run Code Online (Sandbox Code Playgroud)

Ale*_*yne 74

# These are equivalent
_.defer(fn);
setTimeout(fn, 1);
Run Code Online (Sandbox Code Playgroud)

所以defer只需一毫秒setTimeout.(它有一些更方便的功能,但这些并不重要.)


JavaScript已经运行循环.它是单线程的,但它的执行基于事件或定时器开始和停止.每次你的JS引擎启动运行一些代码时,它都会开始运行循环的一次迭代.

那么defer说什么是"在下一个运行循环中运行此代码".

_.defer(function() { alert('after'); });
alert('before');
Run Code Online (Sandbox Code Playgroud)

这会在"之前"和"之后"发出警报.这是因为当前运行循环结束了"之前"警报,然后在新运行循环开始之后立即运行代码警报"之后".

因此,只要您在此处拥有代码,但是您希望它运行首先在此代码之后出现的代码,那么您将使用defer.

_.defer(functionToRunLast);
functionToRunFirst();
Run Code Online (Sandbox Code Playgroud)

这对DOM来说很方便.有时您更改它,但更改不会立即解析或呈现.在运行循环结束时,浏览器赶上并解析并呈现DOM,然后下一个运行循环开始并可以与新呈现的DOM交互.

(究竟是什么情况导致这个延迟的DOM解析,我不确定,但我在过去的自己的项目中已经注意到了.)


不是 DOM准备就绪的替代品.下一个运行循环可能 DOM就绪之前发生,不要混淆这些概念.

  • 我很确定DOM会立即更新,但渲染(以及尺寸和定位之类的东西)通常不会发生,直到浏览器获得控制权之后; 这就是为什么你想要将谷歌地图绑定到你刚添加的东西时经常需要一个`defer`(或等效的`setTimeout`):地图想要知道有多大的东西,但是这些信息直到浏览器有机会计算它. (3认同)
  • 你的答案是正确的,虽然你所谓的"循环"在技术上被称为"消息".消息将添加到队列中.事件循环一次一个地处理每个消息.当您调用setTimeout时,它会将回调放在队列的末尾.https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/EventLoop (3认同)
  • @ whiteb0x这基本上是一回事.查看[下划线源代码](http://underscorejs.org/docs/underscore.html#section-70),你会看到`defer`调用的`delay`时间为'1`,并且`delay `调用`setTimeout`. (2认同)