js 宏任務和微任務 promise


1.概念:宏任務(macrotask )和微任務(microtask ) 表示異步任務的兩種分類。常見宏任務:I/O 、setTimeout、setInterval;微任務:Promise.then catch finally、process.nextTick

在掛起任務時,JS 引擎會將 所有任務 按照類別分到這兩個隊列中,

首先在 macrotask 的隊列(這個隊列也被叫做 task queue)中取出第一個任務,執行完畢后取出 microtask 隊列中的所有任務順序執行;

之后再取 macrotask 任務,周而復始,直至兩個隊列的任務都取完。

2.代碼

2.1 基本執行順序 

// 主線程(外層宏) -  微  -  宏
//  1  1.1  -  2  -  3     
setTimeout(() => {
    console.log('3')
}, 0)
console.log('1');

new Promise((resolve) => {
    console.log('1.1');
    resolve()
}).then(() => {
    console.log('2');
}).then(()=>{
    console.log('2.1')
})
View Code
setTimeout(_ => console.log(4))

new Promise(resolve => {
  resolve()
  console.log(1)
}).then(_ => {
  console.log(3)
})

console.log(2)
View Code

 

        setTimeout(_ => console.log(4))

        new Promise(resolve => {
            resolve()
            console.log(1)
        }).then(_ => {
            console.log(3)
        })

        console.log(2)
View Code
        setTimeout(() => {
            console.log("宏2");
        }, 1000);

        setTimeout(() => {
            console.log("宏3");
        }, 100);

        console.log("同步");

        new Promise((resolve, reject) => {
                setTimeout(() => {
                    console.log("宏1");
                }, 0)
                console.log("立即");
                resolve();
                // reject()
            })
            .then(() => {
                console.log("微0");
            })
            .then(() => {
                console.log("微0");
            })
            .catch(() => {
                console.log("err");
            })

        //  同步  立即   微0  微0   宏1  宏3   宏2
View Code

 

2.2 深度解析案例 :單組依次執行

console.log('1');
setTimeout(function() {
    console.log('3');
    new Promise(function(resolve) {
        console.log('3.1');
        resolve();
    }).then(function() {
        console.log('4')
    })
})

new Promise(function(resolve) {
    console.log('1.1');
    resolve();
}).then(function() {
    console.log('2')
})

setTimeout(function() {
    console.log('5');
    new Promise(function(resolve) {
        console.log('5.1');
        resolve();
    }).then(function() {
        console.log('6')
    })
})
View Code

 2.3 promise ES5實現

function MyPromise(fn) {
    var value = null,
        callbacks = [];
    this.then = function (onFulfilled) {
        callbacks.push(onFulfilled);
        return this;
    };
    function resolve(value) {
        setTimeout(function () {
            callbacks.forEach(function (callback) {
                callback(value);
            });
        },0)
    }
    fn(resolve);
}


function test() {
    return new MyPromise(function(resolve) {
        console.log('1');
        resolve();
    })
}

test().then(function(resolve) {
    console.log('2');
}).then(function(resolve) {
    console.log('3');
});
View Code

 更全的方式

/**
 * Promise類實現原理
 * 構造函數傳入一個function,有兩個參數,resolve:成功回調; reject:失敗回調
 * state: 狀態存儲 [PENDING-進行中 RESOLVED-成功 REJECTED-失敗]
 * doneList: 成功處理函數列表
 * failList: 失敗處理函數列表
 * done: 注冊成功處理函數
 * fail: 注冊失敗處理函數
 * then: 同時注冊成功和失敗處理函數
 * always: 一個處理函數注冊到成功和失敗
 * resolve: 更新state為:RESOLVED,並且執行成功處理隊列
 * reject: 更新state為:REJECTED,並且執行失敗處理隊列
**/

class PromiseNew {
  constructor(fn) {
    this.state = 'PENDING';
    this.doneList = [];
    this.failList = [];
    fn(this.resolve.bind(this), this.reject.bind(this));
  }

  // 注冊成功處理函數
  done(handle) {
    if (typeof handle === 'function') {
      this.doneList.push(handle);
    } else {
      throw new Error('缺少回調函數');
    }
    return this;
  }

  // 注冊失敗處理函數
  fail(handle) {
    if (typeof handle === 'function') {
      this.failList.push(handle);
    } else {
      throw new Error('缺少回調函數');
    }
    return this;
  }

  // 同時注冊成功和失敗處理函數
  then(success, fail) {
    this.done(success || function () { }).fail(fail || function () { });
    return this;
  }

  // 一個處理函數注冊到成功和失敗
  always(handle) {
    this.done(handle || function () { }).fail(handle || function () { });
    return this;
  }

  // 更新state為:RESOLVED,並且執行成功處理隊列
  resolve() {
    this.state = 'RESOLVED';
    let args = Array.prototype.slice.call(arguments);
    setTimeout(function () {
      this.doneList.forEach((item, key, arr) => {
        item.apply(null, args);
        arr.shift();
      });
    }.bind(this), 200);
  }

  // 更新state為:REJECTED,並且執行失敗處理隊列
  reject() {
    this.state = 'REJECTED';
    let args = Array.prototype.slice.call(arguments);
    setTimeout(function () {
      this.failList.forEach((item, key, arr) => {
        item.apply(null, args);
        arr.shift();
      });
    }.bind(this), 200);
  }
}

// 下面一波騷操作
new PromiseNew((resolve, reject) => {
  resolve('hello world');
  // reject('you are err');
}).done((res) => {
  console.log(res);
}).fail((res) => {
  console.log(res);
})
View Code

 2.4 promise 常見用法

鏈式調用:

Promise的精髓是“狀態”,用維護狀態、傳遞狀態的方式來使得回調函數能夠及時調用,它比傳遞callback函數要簡單、靈活的多

超時:

用race給某個異步請求設置超時時間,並且在超時后執行相應的操作

 

3.相關文章

js 宏任務和微任務介紹及實例講解

js 宏任務和微任務

徹底理解setTimeout()

 大白話講解Promise


免責聲明!

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



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