JavaScript 中的同步与非同步
阻塞(blocking)与非阻塞(non-blocking)
const fs = require('fs')const file = fs.readFileSync('./README.md') // 需要等待完成console.log(file)const arr = []for (let i = 2; i <= 99999999; i+=2) { arr.push(i)}console.log(arr)
程式码需要再读去档案的地方等待几秒才能执行下一行动作,fs.readFileSync阻挡了后面程式的执行,这个method就是阻塞(blocking)的,因为程式的执行会一直 block 在这里直到他执行完毕。
流程图 :
const fs = require('fs')// 定义读取档案完成以后,要执行的 functionfunction readFileFinished(err, data) { if (err) { console.log(err) } else { console.log(data) }}// 读取档案,第二个参数是 callback functionfs.readFile('./README.md', readFileFinished);
on-blocking 的 method 执行完 function 以后就可以直接跳下一行了,档案读取完毕以后会把结果传进 callback function,放在上面的程式码中,当执行fs.readFile后,会将他先放到一个地方(后面会解释),让程式能够先执行后面的程式,等到fs.readFile读取完毕后会将读取到的data放到callback funciton中。
流程图 :
同步(synchronous)与非同步(asynchronous)
基本上同步(synchronous)与非同步(asynchronous)可以等于阻塞(blocking)与非阻塞(non-blocking)
1.同步(synchronous)代表执行时程式会卡在那一行,直到有结果为止。
2.非同步(asynchronous)代表执行时不会卡住,但执行结果不会放在回传值,而是需要透过回呼函式(callback function)来接收结果
浏览器上的同步与非同步
在浏览器中使用同步会阻塞后面的执行,若API Server需要读取10秒,整个JavaScript引擎就必须等待10秒才能做下面的动作,会造成整个浏览器无法动作冻结10秒,若要避免此状况就必须让需要等待很久的JavaScript变成非同步并让callback Function来接收结果。
有三种非同步的写法 :
//1. 宣告functionfunction handleResponst() { console.log(response)}getAPIResponse(handleResponst)//2. 匿名函式getAPIResponse(function(err, response) { console.log(response)})//3. 箭头函式getAPIResponse((err, response) => { console.log(response)})
CallBack Function
熟悉的callback function
callback function 的意思:「当某事发生的时候,就使用这个 function 」,虽然乍看之下很陌生但是却常常再用。
HTML : <button id="btn">Click</button>JavaScript : const button = document.getElementById("btn");button.addEventListener("click",handleClick);function handleClick(){ alert("Click");}
「当某事(onclick触发)发生后,会呼叫handleClick这个function」,handleClick就是个 callback function
*使用callback function时要注意传进去的callback function是个 "function" 而不是function的结果,所以不能使用 " function() "
//错误用法const button = document.getElementById("btn");button.addEventListener("click",handleClick());function handleClick(){ alert("Click");}
callback funciotn的参数
Callback 的 error first会习惯放在第一个,因为错误只有一个(读取失败,没有这个档案...)但是回传值却会有很多个,若把err放在最后一个就必须把前面的回传值都填入,这样并不方便,所以将err放在第一个位置就可以控制需要几个回传值。
参考文章 :
JavaScript 中的同步与非同步(上):先成为 callback 大师吧!