js异步编程

参考http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html

 

异步和同步编程思想:做一份卷子的时候,遇到一道难题,同步会仔细想直到解决了才去做下一题,异步是直接跳过这题,然后把其他的都做完了,再做这个难题

同步:上一件事情只有完成才开始下一件事情(js大部分都是同步编程的)

异步:规划做一件事情 但是不是当前立马执行这件事 需要等一定时间,这样的话 我们不会等着它执行 而是执行下面的代码 "只有当下面的代码执行完了 才会返回执行处理之前的事情 如果下面的没执行完 那么不管之前的事情有没有到时间 都必须等着"

在js中异步编程有四种情况:定时器,所有的事件绑定 ,ajax读取数据的时候 ,回调函数

  window.setTimeout(function() {
    console.log(5)
  }, 100)
  window.setTimeout(function() {
    console.log(3)
  }, 10)
  window.setTimeout(function() {
    console.log(4)
  }, 10)
  window.setTimeout(function() {
    console.log(2)
  }, 0)
  console.log(1)

会依次打印1,2,3,4,5

浏览器看到定时器,会记录当前定时器多久以后执行,即使定时器定时0,浏览器会将其变成自己最小的定时时间,然后排队,时间越短的越排在前面,同样时间的按出现的先后,排队完后,再执行(无视作用域)其他代码,最后执行排好的队列

 

为了防止出错,自己写这些异步的时候,写个注释,还有不影响整体代码的情况下,尽可能靠后写

 

有个经典案例,有5个li,每个里面的文本是当前索引,点击li,显示相应的索引

然后就这样写:

var lis = document.getElementsByTagName("li");
  for (var i = 0; i < lis.length; i++) {
    var cur = lis[i];
    lis[i].onclick = function () {
      console.log(i)
    }
  }

结果发现点击什么都是打印5,分析下,浏览器执行的时候,遇到for,首先i=0,然后绑定点击事件,请注意,当绑定事件的时候,只是绑定一个函数,里面是什么根本没管,然后循环完之后,i=5,此时,每个li上都有绑定事件,当点击某一个li的时候,执行函数,打印i,而i已经变成了5.

正确的做法是保留i,比如

var lis = document.getElementsByTagName("li");
  for (var i = 0; i < lis.length; i++) {
    var cur = lis[i];
    cur["index"] = i;
    lis[i].onclick = function () {
      console.log(this["index"])
    }
  }

 然后看这个demo

function a() {
  window.setTimeout(function() {
    console.log(5)
  }, 100)
  window.setTimeout(function() {
    console.log(3)
  }, 0)
  console.log(1)
}
function b() {
  window.setTimeout(function() {
    console.log(6)
  }, 100)
  window.setTimeout(function() {
    console.log(4)
  }, 0)
  console.log(2)
}
a()
b()

依然会依次输出1,2,3,4,5,6,也就是说跨作用域,浏览器的队列和作用域无关,只要是定时器都会在普通代码之后执行.

posted @ 2017-02-16 17:37  花.花  阅读(191)  评论(0编辑  收藏  举报