神奇的setTime(func, 0)

背景:
在一个页面中我们需要利用动态创建iframe并添加相应的CSS文件来实现网页的局部打印, 于是就有了下面这段代码:

1  
2
      $printDetailFrame = $(‘<iframe>‘, {
3
                           src: "",
4
                           id:  "printFrame",
5
                           frameborder: 0,
6
                           scrolling: "no",
7
                           style: "display:none"
8
                          }).appendTo("body")
9  

紧接着我们再把CSS添加到这个动态创建的iframe,

1  
2
   $printCSSReset = $("link[href*=‘reset.css‘]").clone(),
3
   $printCSSReports = $("link[href*=‘reports.css‘]").clone(),
4
   $printCSSUnf = $("link[href*=‘unf.css‘]").clone();
5
   $printDetailFrame
6
    .contents()
7
     .find("head")
8
      .append($printCSSReset,$printCSSReports,$printCSSUnf);
9  

发现问题:
到目前为止, 一切都看起来很正常, 然后在需要打印时候

1  
2
//把要打印的区域加入到iframe内部
3
......
4
$printDetailFrame.get(0).contentWindow.print()
5  

在Chrome上测试时候, 打印可以达到预想效果,也就是说我们插入的CSS链接起到了作用, 但是在Firefox 30.0上测试时发现,
打印完全没有预想中的效果, 也就是CSS根本没有起到作用,经过检查动态创建的iframe里面没有任何css添加进去, 这是神马情况?

原来我们忽略了一个问题:
我们在添加CSS代码是在创建iframe之后立即运行的, 但是我们并不能保证iframe已经在页面DOM上创建完成了,
若是在没有创建好iframe的情况下, 在iframe上添加CSS链接就是一个没有实际运行结果的代码, 因为这时候根本就找不到那个iframe.
如何解决呢? 这时候就该我们的主角setTimeout登场了。

解决:
我们把添加CSS那段代码放入一个setTimeout里面, 如下:

1  
2
  setTimeout(function(){
3
   $printDetailFrame
4
    .contents()
5
     .find("head")
6
      .append($printCSSReset,$printCSSReports,$printCSSUnf);
7
  }, 0);
8  

分析:
当我们在页面上动态创建一个iframe时候, 实际上是通知浏览器内核页面渲染进程去创建, 并在js自己的事件列队中插入了一个回调等待,
但是js把这个事情抛给浏览器后就直接继续运行下面的添加CSS代码, 或许是每个浏览器进程调度机制不同,
在firefox就出现了我们上面说的这个问题, 那么ssetTimeout(func, 0)是起到了什么作用呢?
它其实就是把func这个方法加入到事件列队中,这样等iframe在页面上创建完毕, js队列就寻找下个回调也就是func这个函数来运行,
这样我们就让这两个有依赖关系的操作按顺序进行.

参考阅读:

http://blog.csdn.net/kongls08/article/details/6996518

http://stackoverflow.com/questions/779379/why-is-settimeoutfn-0-sometimes-useful

最后的补充:
我们也可以尝试利用jQuery的deffered机制来代替setTimeout, 但这个还需要测试才能确定可行性:

1  
2
  $printDetailFrame.promise().done(function(){
3
   $printDetailFrame
4
    .contents()
5
     .find("head")
6
      .append($printCSSReset,$printCSSReports,$printCSSUnf);
7
  });
8  

神奇的setTime(func, 0),布布扣,bubuko.com

时间: 2024-12-17 10:43:34

神奇的setTime(func, 0)的相关文章

Javascript定时器(三)——setTimeout(func, 0)

setTimeout(func, 0)可以使用在很多地方,拆分循环.模拟事件捕获.页面渲染等 一.setTimeout中的delay参数为0,并不是指马上执行 <script type="text/javascript"> function delay1() { console.log('delay1'); } function delay2() { console.log('delay2'); } function delay3() { console.log('dela

javascript setTimeout 0

本文提供了一个 javascript 方面的 setTimeout 的一个例子,在执行长时间的堵塞任务时,相关页面渲染会有问题,直接提供代码,拿代码说例子是最简单的: <html> <script src= "js/jquery-1.10.2.min.js" type="text/javascript"></ script> <body> <button id= 'do'>Do long calc!<

如何从0搭建用户成长体系?

在我刚开始接触Python语言的日子里,我最喜欢做的事情之一是坐在解释器旁使用内置help功能来检查类和方法,决定下一个要敲的内容.这个功能导入一个对象,遍布它的成员,取出文档注释,生成一个类似manpage的输出,从而帮助你找到如何使用正在检查的对象的方法. 它被内置成一个标准库的美妙之处在于通过代码直接生成输出,它为我这样的懒人间接地强调了一个编码风格,我就想着在尽量少做额外的工作的情况下维护文档.尤其是如果你已经为你的变量和函数选择直接的名字. 这种风格涉及到向你的函数和类添加文档字符串,

C# 3.0 LINQ的准备工作

局部变量 隐式类型允许你用var修饰类型.用var修饰只是编译器方便我们进行编码,类型本身仍然是强类型的,所以当编译器无法推断出类型时(例如你初始化一个变量却没有为其赋值,或赋予null,此时就无法推断它的类型),用var修饰就会发生错误.另外,只能对局部变量使用隐式类型. 使用隐式类型的几个时机: 当变量的类型太长或者难以推测,但类型本身不重要时,比如你的LINQ语句中用了Groupby,那么一般来说基本很少人可以准确地推测出结果的类型吧... 当变量初始化时,此时可以根据new后面的类型得知

Apache Spark-1.0.0源码浅析(三 ):作业提交

RDD的操作可以分为Transformations和Actions,Transformations是lazy的不立即执行,Action则会触发作业的提交和执行.例如本例中的foreach def foreach(f: T => Unit) { sc.runJob(this, (iter: Iterator[T]) => iter.foreach(f)) } 一句话,Actions调用sc.runJob触发作业运行. SparkContext中的runJob有多个版本的重载 foreach调用的

python2.0 s12 day4

python2.0 s12 day404 python s12 day4 TengLan回顾上节内容 05 python s12 day4 迭代器原理及使用 本节大纲介绍: 1.迭代器&生成器 2.装饰器 1.基本装饰器 2.多参数装饰器 3.递归 4.算法基础:二分查找 二维数组转换 5.正则表达式 6.常用模块学习 7.作业 1.迭代器&生成器 1)迭代器 定义: 就是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束. 优点: 不需要事先准备好整

linux 操作系统下c语言编程入门

2)Linux程序设计入门--进程介绍 3)Linux程序设计入门--文件操作 4)Linux程序设计入门--时间概念 5)Linux程序设计入门--信号处理 6)Linux程序设计入门--消息管理 7)Linux程序设计入门--线程操作 8)Linux程序设计入门--网络编程 9)Linux下C开发工具介绍 1)Linux程序设计入门--基础知识 Linux下C语言编程基础知识 前言: 这篇文章介绍在LINUX下进行C语言编程所需要的基础知识.在这篇文章当中,我们将 会学到以下内容: 源程序编

PHP5.2至5.6的新增功能详解

截至目前(2014.2), PHP 的最新稳定版本是 PHP5.5, 但有差不多一半的用户仍在使用已经不在维护 [注] 的 PHP5.2, 其余的一半用户在使用 PHP5.3 [注].因为 PHP 那"集百家之长"的蛋疼语法,加上社区氛围不好,很多人对新版本,新特征并无兴趣.本文将会介绍自 PHP5.2 起,直至 PHP5.6 中增加的新特征. PHP5.2 以前:autoload, PDO 和 MySQLi, 类型约束 PHP5.2:JSON 支持 PHP5.3:弃用的功能,匿名函数

单线程 异步 同步 阻塞 非阻塞

Javascript是单线程的深入分析 首先一个引子:为什么JavaScript是单线程的却能让AJAX异步发送和回调请求,还有setTimeout也看起来像是多线程的? 先看例子1: 1 function foo() { 2 console.log( 'first' ); 3 setTimeout( ( function(){ console.log( 'second' ); } ), 5); 4 } 5 for (var i = 0; i < 1000000; i++) { 6 foo();