Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

同步与异步 #57

Open
yym-yumeng123 opened this issue Dec 20, 2018 · 0 comments
Open

同步与异步 #57

yym-yumeng123 opened this issue Dec 20, 2018 · 0 comments

Comments

@yym-yumeng123
Copy link
Owner

Javascript同步与异步最大的区别就是

  • 同步(Synchronous): 等待结果
  • 异步(Asynchronous): 不等待结果

注意 : 异步常常伴随着回调一起出现, 但是异步不是回调,回调也不是异步

同步

如果函数是同步的,即使调用函数执行任务比较耗时,也会一致等待直到得到执行结果。

function wait(seconds){
    var time = new Date()
    while(new Date() - time < seconds * 1000){}
    return
}
console.log(1)
wait(5);
console.log('慢死了')
console.log(2)

同步等待的结果, 等待5秒,打印2,这就是同步

异步: 现在与将来

  • 使用像 JavaScript 这样的语言编程时,很重要但常常被误解的一点是,如何表达和控制持续一段时间的程序行为
  • 它是指程序的一部分现在运行,而另一部分则在将来运行——现在和将来之间有段间隙,在这段间隙中,程序没有活跃执行。
  • 实际上,所有重要的程序(特别是 JavaScript 程序)都需要通过这样或那样的方法来管理这段时间间隙,这时可能是在等待用户输入、从数据库或文件系统中请求数据、通过网络发送数据并等待响应,或者是在以固定时间间隔执行重复任务(比如动画)。
  • 程序中现在运行的部分和将来运行的部分之间的关系就是异步编程的核心。
function wait(seconds, fn) {
	setTimeout(fn, seconds * 1000)
}
console.log(1)
wait(5, ()=> console.log('wait...'))
console.log(2)

任何时候,只要把一段代码包装成一个函数,并指定它在响应某个事件(定时器、鼠标点 击、Ajax 响应等)时执行,你就是在代码中创建了一个将来执行的块,也由此在这个程序 中引入了异步机制
异步不等待结果, 时间到了打印 wait...

JS引擎

  • JS引擎:js引擎可以说是js虚拟机,负责解析js代码的解析和执行。通常以下步骤:
    • 词法解析:将源代码分解位有意义的分词
    • 语法分析:用语法分析器将分词解析成语法树
    • 代码生成:生成机器能运行的代码
    • 代码执行

不同浏览器的js引擎也各不相同,Chrome用的是V8,FireFox用的是SpiderMonkey,Safari用的是JavaScriptCore,IE用的是Chakra。
之所以说js是单线程就是因为浏览器运行时只开启一个js解释器,原因是若有两个线程操作DOM,浏览器就又晕了。
JavaScript是单线程的,但是浏览器不是单线程的。一些I/O操作,定时器的计时和事件监听是由其他线程完成的。

// 同步: 
                             5s后
JS引擎 ==> console.log(1) ----------- 同步 wait(5)  ==>  console.log(2)
0s ---------------------------------------------------------------------------------------------- ns 时间(time/s)
// 异步: 
浏览器-------------------------------------
                                          | 设置时间, 每段时间检查 -------
                                          |                            |
                                          |                            | 时间到了通知
                       打印console.log(2) |                            |=================>
JS引擎 ==> console.log(1) ----------- 异步 wait(5) / setTImeout(fn, s) 什么也没做 ==> 时间到 执行 fn
0s ---------------------------------------------------------------------------------------------- ns 时间(time/s)

JavaScript 引擎本身所做的只不过是在需要的时候,在给定的任意时刻执行程序中的单个代码块。


事件循环

尽管你显然能够编写异步 JavaScript 代码(就像前面我们看到的定时代码),但直到最近(ES6),JavaScript 才真正内建有直接的异步概念。

JavaScript 引擎并不是独立运行的,它运行在宿主环境中,对多数开发者来说通常就是Web 浏览器。经过最近几年(不仅于此)的发展,JavaScript 已经超出了浏览器的范围,进入了其他环境,比如通过像 Node.js 这样的工具进入服务器领域。实际上,JavaScript 现如今已经嵌入到了从机器人到电灯泡等各种各样的设备中。

但是,所有这些环境都有一个共同“点”(thread,也指线程。不论真假与否,这都不算一个很精妙的异步笑话),即它们都提供了一种机制来处理程序中多个块的执行,且执行每块时调用 JavaScript 引擎,这种机制被称为事件循环

什么是事件循环?

// 伪代码
// eventLoop是一个用作队列的数组
// (先进,先出)
var eventLoop = [ ];
var event;
// “永远”执行
while (true) {
	// 一次tick
	if (eventLoop.length > 0) {
		// 拿到队列中的下一个事件
		event = eventLoop.shift();
		// 现在,执行下一个事件
		try {
			event();
		}
		catch (err) {
			reportError(err);
		}
	}
}

有一个用 while 循环实现的持续运行的循环,循环的每一轮称为一个 tick。对每个 tick 而言,如果在队列中有等待事件,那么就会从队列中摘下一个事件并执行。这些事件就是你的回调函数。

一些异步代码

var width = document.getElementsByTagName('img')[0].width  //width: 0
// 图片加载需要时间
var img = document.getElementsByTagName('img')[0]
img.onload = function () {
	var width = img.width
	console.log(width)
}
let liList = document.querySelectorAll('li')
for(var i = 0; i < liList.length; i++) {
	liList[i].onClick = function() {
		console.log(i)
	}
}
==> 
let liList = document.querySelectorAll('li')  // 加入有 6 li
var i  // 点击事件后才执行 log(i)  当 i = 6时
for(i = 0; i < liList.length; i++) {
	liList[i].onClick = function() {
		console.log(i)  // 6
	}
}

let liList = document.querySelectorAll('li')
for(let i = 0; i < liList.length; i++) {
	liList[i].onClick = function() {
		console.log(i) // 0 1 2 3 4 5
	}
}
let response = $.ajax({
  url: '.',
  async: false,  // 同步
})

let response = $.ajax({
  url: '.',
  async: true,  // 异步
  success: function() {
    console.log('123')
  }
})

回调

Promise

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant