javascript宏任務和微任務


函數

// 你不能改變一個函數的 name 屬性的值, 因為該屬性是只讀的
var object = {
  // someMethod 屬性指向一個匿名函數
  someMethod: function() { }
};
object.someMethod.name = "otherMethod";
console.log(object.someMethod.name); // someMethod

函數的length屬性等於該函數聲明時所要傳入的新參數量
通過arguments.length,可以知道在調用時傳入了多個參數

setTimeout()和setInterval()的區別

setTimeout(()=>{
    console.log('執行setTimeout')
},1000)
setInterval(()=>{
    console.log('執行setInterval')
},1000)
setTimeout是執行並延遲1s執行
只有滿足 (1)3秒后 (2)主線程空閑,同時滿足時,才會3秒后執行該函數
setInterval是每隔1s就嘗試執行

setTimeout、setInterval被遺忘的第三個參數

for ( var i=1; i<=5; i++) {
	setTimeout( function timer(j) {
		console.log( j );
	}, i*1000, i);
}
第三個參數param1,param2l...
作為參數傳遞給function或者字符串中的參數

event loop的概念

微任務 promise  process.nextTick          
宏任務 setTimeout  setInterval  I/O  script
同一次事件循環中  微任務永遠在宏任務之前執行

 setTimeout(function(){
     console.log('定時器開始啦')
 });
 
 new Promise(function(resolve){
     console.log('馬上執行for循環啦');
     for(var i = 0; i < 10000; i++){
         i == 99 && resolve();
     }
 }).then(function(){
     console.log('執行then函數啦')
 });
 
 console.log('代碼執行結束');
首先執行script下的宏任務,遇到setTimeout,將其放到宏任務的【隊列】里

遇到 new Promise直接執行,打印"馬上執行for循環啦"

遇到then方法,是微任務,將其放到微任務的【隊列里】

打印 "代碼執行結束"

本輪宏任務執行完畢,查看本輪的微任務,發現有一個then方法里的函數, 打印"執行then函數啦"

到此,本輪的event loop 全部完成。


下一輪的循環里,先執行一個宏任務,發現宏任務的【隊列】里有一個 setTimeout里的函數,執行打印"定時器開始啦"

【馬上執行for循環啦 --- 代碼執行結束 --- 執行then函數啦 --- 定時器開始啦】

async function fn1(){
    return 123
}

function fn2(){
    return 123
}

console.log(fn1())
console.log(fn2())
//返回
Promise {<resolved>: 123}
123
-----
new promise(()=>{
    同步的
}).then(
異步的微任務
)

第二題

setTimeout(() => console.log('setTimeout1'), 0);  //1宏任務
setTimeout(() => {								//2宏任務
    console.log('setTimeout2');
    Promise.resolve().then(() => {
        console.log('promise3');
        Promise.resolve().then(() => {
            console.log('promise4');
        })
        console.log(5)
    })
    setTimeout(() => console.log('setTimeout4'), 0);  //4宏任務
}, 0);
setTimeout(() => console.log('setTimeout3'), 0);  //3宏任務
Promise.resolve().then(() => {//1微任務
    console.log('promise1');
})

第三題

async function async1() {
    console.log( 'async1 start' )
    await async2()
    console.log( 'async1 end' )
}
async function async2() {
    console.log( 'async2' )
}
async1()
console.log( 'script start' )

執行結果
async1 start
async2
script start
async1 end

一旦遇到await 就立刻讓出線程,阻塞后面的代碼

等候之后,對於await來說分兩種情況

  • 不是promise 對象
  • 是promise對象

如果不是promise,await會阻塞后面的代碼,先執行async外面的同步代碼,同步代碼執行完畢后,在回到async內部,把promise的東西,作為await表達式的結果

如果它等到的是一個 promise 對象,await 也會暫停async后面的代碼,先執行async外面的同步代碼,等着 Promise 對象 fulfilled,然后把 resolve 的參數作為 await 表達式的運算結果。

如果一個 Promise 被傳遞給一個 await 操作符,await 將等待 Promise 正常處理完成並返回其處理結果。

第四題

        async function async1() {
            console.log( 'async1 start' ) //2
            await async2()
            console.log( 'async1 end' )//7
        }
        async function async2() {
            console.log( 'async2' )//3
        }
        console.log( 'script start' ) //1
        setTimeout( function () {
            console.log( 'setTimeout' )//8
        }, 0 )
        async1();
        new Promise( function ( resolve ) {
            console.log( 'promise1' )//4
            resolve();
        } ).then( function () {
            console.log( 'promise2' ) //6
        } )
        console.log( 'script end' )//5

控制台執行任何語句都認為是在一個匿名函數空間包裹下的,JS函數return; 和不寫return都是默認返回undefined,所以會在控制台下輸出undefined

第五題

       new Promise( ( resolve, reject ) => {
                console.log( "promise1" )
                resolve()
            } )
            .then( () => {
                console.log( 1 )
            } )
            .then( () => {
                console.log( 2 )
            } )
            .then( () => {
                console.log( 3 )
            } )

        new Promise( ( resolve, reject ) => {
                console.log( "promise2" )
                resolve()
            } )
            .then( () => {
                console.log( 4 )
            } )
            .then( () => {
                console.log( 5 )
            } )
            .then( () => {
                console.log( 6 )
            } )
        // 1 4 2 5 3 6

先執行同步代碼 promise1, promise2,此時微任務有兩個任務 log(1)和log(4)

執行完log(1)和log(4)此時任務中有log(2)和log(5)兩個微任務

執行log(2)和log(5)此時任務中有log(3)和log(6)兩個微任務

連續的幾個then()回調,並不是連續的創建了一系列的微任務並推入微任務隊列,因為then()的返回值必然是一個Promise,而后續的then()是上一步then()返回的Promise的回調

ECS(執行環境棧)

function foo(i) {
  if (i < 0) return;
  console.log('begin:' + i);
  foo(i - 1);
  console.log('end:' + i);
}
foo(2);

// 輸出:

// begin:2
// begin:1
// begin:0
// end:0
// end:1
// end:2

**執行棧既是函數在執行時存儲調用過程的棧,同樣的,采取調用形式進行隊列,先進后出的方式 **

第六題

async function t1 () {
  console.log(1)
  console.log(2)
  await Promise.resolve().then(() => console.log('t1p'))
  console.log(3)
  console.log(4)
}

async function t2() {
  console.log(5)
  console.log(6)
  await Promise.resolve().then(() => console.log('t2p'))
  console.log(7)
  console.log(8)
}

t1()
t2()

console.log('end')

// 輸出:
// 1
// 2
// 5
// 6
// end
// t1p
// t2p
// 3
// 4
// 7
// 8
// undefined

第七題

async function t1 () {
  console.log(1)
  console.log(2)
  await new Promise(resolve => {
    setTimeout(() => {
      console.log('t1p')
      resolve()
    }, 1000)
  })
  await console.log(3)
  console.log(4)
}

async function t2() {
  console.log(5)
  console.log(6)
  await Promise.resolve().then(() => console.log('t2p'))
  console.log(7)
  console.log(8)
}

t1()
t2()

console.log('end')

// 輸出:
// 1
// 2
// 5
// 6
// end
// t2p
// 7
// 8
// undefined
// t1p
// 3
// 4


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM