声明
本文不涉及如何优雅的设计和实现异步编程,只是从最基础的方面阐述异步、同步编程的方式。
如想优化实现,请移步:
(似乎不应该放在这里,可能你们看到这里就直接跳走了-_#,所以,
亲,别走,留下来~~)
开篇
先看个例子:
console.log('1'); setTimeout(function(){ console.log('first time'); }, 10); console.log('2'); var flag = true; setTimeout(function(){ flag = false; console.log('second time'); }, 0); var t_start = Number(new Date()); //延迟一秒才执行 while ( t_start + 1000 > Number(new Date()) ) { console.log(flag); } console.log('last ' + flag);
输出:
(忽略红色错误)从上面的输出可以看出,setTimeout的执行都被
挂起来了,等函数的其它部分都执行完毕后,才会开始执行;
所以,即使setTimeout在0ms后立即执行,最后也是在while循环等待了1s之后,才真正执行,即while是会阻塞setTimeout的;
还有,second time在first time之前输出,因为first time等待了10ms,如果将这个10ms改为0,那么这两个输出就会调换位置。
而造成上面这一切的根本原因就是:js的运行是
单线程的,当一个程序占着cpu狂奔的时候,其它人无法打断,只有等待。
接下来,说明下同步和异步:
由于单线程,按理说js的执行应该是从上至下顺序的,同步执行就是js原本的样子。
说到异步,可能创始人Brendan Eich也没有想过会有这种实现,随着web页面的丰富和发展,展现越来越慢,后人慢慢的创新了异步这种方式,如图:
技术上的解释就是:
异步就是延时,延时就是在等待(by司徒)
最终目的就是:当一个耗时的任务需要执行时,应该将它异步分发出去,以便及时响应用户的请求。
那么将同步的函数转为异步的方式有哪些呢?下面就来一一说明:
1、setTimeout和setInterval
话不多说,请看开篇的例子。
setInterval跟setTimeout一样,运行时,被挂起,后续的函数不会等待interval中的事件执行完毕才开始,而是立马开始。
当然,这两个生成的异步都可以控制时间,可以自主控制多少秒后才会fire。
2、image.onload和image.onerror
代码:
var<