由于JavaScript的執(zhí)行環(huán)境是單線程的,導(dǎo)致js代碼的兩種執(zhí)行方式:
- 以js代碼的先后順序執(zhí)行的順序型
- 以事件驅(qū)動(dòng)觸發(fā)執(zhí)行的事件型
以js代碼的先后順序執(zhí)行的順序型
也就是所謂的同步執(zhí)行,相對(duì)于位置靠前的代碼執(zhí)行完成,才去執(zhí)行后續(xù)的代碼
console.log('1');
console.log('2');
以事件驅(qū)動(dòng)觸發(fā)執(zhí)行的事件型
function c(){
console.log('3');
}
console.log('1');
onclick = c();
console.log('2');
異步執(zhí)行:只要不阻斷js主線程執(zhí)行而執(zhí)行的代碼都是異步執(zhí)行,以上點(diǎn)擊事件觸發(fā)函數(shù)c()的執(zhí)行并不影響后續(xù)代碼執(zhí)行;所以所有的事件觸發(fā)函數(shù)都是異步執(zhí)行,也就是第一種異步執(zhí)行方式:事件監(jiān)聽
從
onclick = c();我們探討異步執(zhí)行的第二種方式:發(fā)布-訂閱模式:
首先onclick是js原生事件,那么換成我們自定義的事件,就構(gòu)成了所謂的發(fā)布訂閱模式,自定義事件參照自定義事件
- 訂閱
Event.on('click',fn) - 發(fā)布
Event.emit('click')
以上我們自定義的事件
click的觸發(fā)fn的執(zhí)行不影響主線程的執(zhí)行順序,所以fn函數(shù)代碼為異步執(zhí)行;從事件的發(fā)布訂閱模式,我們探討第三種異步執(zhí)行方式:回調(diào)函數(shù)
const event = {};
function on(type,callback){
event.type = callback;
}
function emit(type){
event.type();
}
以上就是最簡(jiǎn)單的一個(gè)事件的發(fā)布訂閱,可以看出歸根結(jié)底就是一個(gè)
callback的執(zhí)行,以下是一個(gè)簡(jiǎn)單的異步回調(diào):
function A(callback){
console.log("I am A");
callback();
console.log("I am C")
}
function B(){
setTimeout(function(){
console.log("I am B");
},1000)
}
A(B);
從回調(diào)函數(shù)我們探討第四種異步執(zhí)行方式
promise:
class Promisser{
constructor(callback) {
this.res = this.res.bind(this);
this.rej = this.rej.bind(this);
this.state = {};
callback(this.res,this.rej)
}
res(val){
this.state.success = val
}
rej(err){
this.state.error = err
}
then(resCallback,rejCallback){
Object.defineProperty(this.state,'success',{
get: function () {
return this.state
},
set: function (newValue) {
resCallback(newValue);
}
})
Object.defineProperty(this.state,'error',{
get: function () {
return this.state
},
set: function (newValue) {
rejCallback(newValue);
}
})
}
}
const test = new Promisser(function(res,rej){
setTimeout(()=>{
res('success')
},1000)
setTimeout(()=>{
rej('error')
},2000)
})
test.then((res)=>{
console.log('111111',res) //111111 success
},(rej)=>{
console.log('222222',rej) //222222 error
})
以上是一個(gè)簡(jiǎn)單的
promiss原生模擬實(shí)現(xiàn),可以看出,歸根結(jié)底也是監(jiān)聽對(duì)應(yīng)狀態(tài)的變化觸發(fā)對(duì)應(yīng)callback的執(zhí)行,只是執(zhí)行的位置移到了函數(shù)外部;
綜上所述
js中異步執(zhí)行的方式:事件監(jiān)聽,事件的發(fā)布-訂閱,
promise對(duì)的異步執(zhí)行原理都是回調(diào)函數(shù),也是js異步執(zhí)行的主要方式;
其他異步執(zhí)行方式
另外的異步執(zhí)行方式es6的新式api Generator函數(shù)與之對(duì)應(yīng)的語(yǔ)法糖
async函數(shù),這里不做討論。