前端的異步流程
1.要知道js腳本語言是單線程的,異步流程的指的就是就是將任務是放在異步隊列中,異步隊列只有在主線程執行完之后采取執行
異步隊列的理解:
js中異步隊列可以分為兩類,marcotask隊列和microtask隊列, marcotask隊列里面包含有1.script中的所有同步代碼,2.setTimeout,3. setInterval,4.setImmediate5. I/O操作, 6. UI渲染,而microtask隊列主要是有1.process,2.nextTick, 3.promise等等, 異步隊列執行的順序主要是 先從marcotask中取出一個任務(第一次就是取出所有同步的代碼),執行完成之后從microtask隊列取出所有的任務,執行完成之后, 再從marcotask隊列中取出一個, 循環往復,直到所有隊列的任務被完成.
2.實現前端異步流程的方式
-
傳統的原生異步
- 回調函數
- 事件
-
使用異步流程工具
-
es6 Promise
Promise 是異步編程的一種解決方案,比傳統的解決方案–回調函數和事件--更合理和更強大。它由社區最早提出和實現,ES6將其寫進了語言標准,統一了語法,原生提供了Promise
所謂Promise ,簡單說就是一個容器,里面保存着某個未來才回結束的事件(通常是一個異步操作) 的結果。從語法上說,Promise是一個對象,從它可以獲取異步操作的消息。 三種狀態:
pending:進行中
fulfilled(resolve) :已經成功
rejected 已經失敗
狀態改變:
Promise對象的狀態改變,只有兩種可能:
從pending變為fulfilled
從pending變為rejected。這兩種情況只要發生,狀態就凝固了,不會再變了,這時就稱為resolved(已定型)
const p1 = new Promise( (resolve,reject ) => {
resolve('任務一')
}).then ( data => {
console.log( data )
})
const p3 = new Promise( ( resolve,reject ) => {
setTimeout( () => {
resolve('任務三')
},2000)
}).then ( data => {
console.log(data)
})
const p2 = new Promise( (resolve,reject) => {
setTimeout( () => {
resolve('任務二')
},1000 )
}).then ( data => {
console.log(data)
})
console.log('主線程任務')
// 主線程任務
// 任務一
// 任務二
// 任務三
es6 generator函數
在function關鍵字后面加一個* 這樣定義的函數就叫做generator函數
通過yield關鍵字來定義任務
通過fn().next() 來執行任務
value表示yield關鍵字后任務執行的結果
done表示當前定義的所有的任務是否執行完成的一個狀態
理解:
多任務的定義,多任務執行
讓自己定義的多個任務依次執行,上一個任務如果沒有完成,下一個任務就不會開始
function* fn () {
yield '任務一'
yield '任務二'
yield '任務三'
return '任務'
}
const a = fn ()
console.log( a.next() )
console.log( a.next() )
console.log( a.next() )
console.log( a.next() )
console.log('主線程任務')
// { value: '任務一', done: false }
// { value: '任務二', done: false }
// { value: '任務三', done: false }
// { value: '任務', done: true }
// 主線程任務
es6 async 函數
配合關鍵字await使用,await 表示,等待,任務一執行結束之后,才會執行任務二
async function fn () {
const result = await '任務一'
console.log( result )
console.log('任務二')
}
fn()
const fn1 = async () => {
const res = await '任務3'
console.log( res )
console.log( '任務四' )
}
fn1()
// 任務一
// 任務二
// 任務3
// 任務四