深入理解ES6 011【學習筆記】

Promise與異步編程

因為執行引擎是單線程的,所以需要跟蹤即將運行的代碼,那些代碼被放在一個任務隊列中,每當一段代碼準備執行時,都會被添加到任務隊列中,每當引擎中的一段代碼結束執行,事件循環會執行隊列中的一下個任務。

Promise相當於異步操作結果佔位符,它不會去訂閱一個事件,也不會傳遞一個回調函數給目標函數,而是讓函數返回一個Promise,就像這樣

// readFile承諾在未來的某個刻完成
let promise = readFile('txx.txt')

Promise的生命週期

  • pending
  • fulfilled 成功
  • rejected 程序錯誤或一些其他原因

[[PromiseState]]內部屬性被用來表示Promise的3種狀態,這個屬性不暴露在Promise對象上,所以不能以編程的方式檢測Promise的狀態,只有當Promise狀態改變時,通過then()方法來採取特定的行為。所以Promise都有then方法,它接受兩個參數,fulfilled和rejected時的兩個回調函數

如果一個對象實現了上述的then方法,那這個對象我們就稱之為thenable對象,所有的Promise對象都是thenable對象,但並非所有thenable對象都是Promise。

let promise = readFile("example.txt");
promise.then(function(contents){
  // 完成
},function(err){
  // 拒絕
})
promise.then(function(contents){
  // 完成
})

promise.then(null,function(err){
  // 拒絕
})
// catch等同於上面這種
promise.catch(function(err){
  // 拒絕
})

如果向Promise.resolve()方法或Promise.reject()方法傳入一個Promise,那麼這個Promise會被直接返回

Nodejs環境的拒絕處理

  • unhandledRejection
  • rejectionHandled
let rejected;
process.on("unhandledRejection",function(reason,promise){
  console.log(reason.message); // "Explosin"
  console.log(rejected === promise); // "Explosin"
})
rejected = Promise.reject(new Error('Explosin'))

串聯Promise及鏈式返回值

let p1 = new Promise(function(resolve,reject){
  resolve(42)
})
p1.then(function(value){
  console.log(value)
  return value+1;
})
.then(function(value){
  console.log(value); // "43"
})

let p1 = new Promise(function(resolve,reject){
  reject(42)
})
p1.catch(function(value){
  console.log(value) // 42
  return value+1;
})
.then(function(value){
  console.log(value); // "43"
})

在Promsie鏈返回Promise

Promise.all()

只接受一個參數並返回一個Promise,該參數是一個含有多個受監視Promise的可迭代對象,只有當可迭代對象中所有Promise都被解決後返回的Promise才會被解決,只有當可迭代對象中所有Promise都完成後返回的promise才會被完成。只要有一個reject,就不用等所有的都完成就會被reject。

let p1 = new Promise(function(resolve,reject){
  resolve(42)
})
let p2 = new Promise(function(resolve,reject){
  reject(43)
})
let p3 = new Promise(function(resolve,reject){
  resolve(44)
})
let p4 =  Promise.all([p1,p2,p3])
p4.catch(function(value){
  console.log(Array.isArray(value)); //false
  console.log(value); // 43
})

Promise.race()

只要有一個resolve,不用等所有的都被完成。一旦數組中的某個Promise被完成,Promise.race()方法也會像Promise.all()方法一樣返回一個特定的Promise

Promise繼承

class MyPromise extends Promise {
  // 使用默認的構造函數

  success(resolove,reject){
    return this.then(resolove,reject)
  }
  failure(reject){
    return this.catch(reject)
  }
}
let promise = new MyPromise(function(resolve,reject){
  resolve(42)
})
promise.success(function(value){
  console.log(value) // 42
})
.failure(function(value){
  console.log(value)
})

基於Promise的異步任務執行

改造之前的文件讀取功能。只要每個異步操作都返回Promise,就可以極大地簡化並能用化這個過程。以Promise作為通用接口用於所有異步代碼可以簡化任務執行器。

let fs = require("fs");

function run(taskDef){
  // 創建迭代器
  let task = taskDef()

  // 開始執行任務
  let result = task.next();

  // 遞歸函數遍歷
  (function step(){
    // 如果有更多任務要做
    if(!result.done){
      // 用一個Promise來解決會簡化問題
      let promise = Promise.resolove(result.value);
      promise.then(function(value){
        result = task.next(value);
        step()
      })
      .catch(function(error){
        result = task.throw(error);
        step();
      })
    }

  }())
}
// 定義一個可用於任務執行器的函數
function readFile(filename){
  return new Promise(function(resolove,reject){
    fs.readFile(filename,function(err,contents){
      if(err){
        reject(err);
      } else {
        resolove(contents)
      }
    })
  })
}

// 執行一個任務
run(function *(){
  let contents = yield readFile("config.json");
  doSomethingWith(contents);
  console.log("Done")
})

主題測試文章,只做測試使用。發佈者:Walker,轉轉請注明出處:https://walker-learn.xyz/archives/4337

(0)
Walker的頭像Walker
上一篇 2025年3月8日 13:04
下一篇 2025年3月8日 12:52

相關推薦

  • 深入理解ES6 008【學習筆記】

    迭代器(Iterator)和生成器(Generator) 這個新特性對於高效的數據處理而言是不可或缺的,你也會發現在語言的其他特性中也都有迭代器的身影:新的for-of循環、展開運算符(...)、甚至連異步編程都可以使用迭代器。 迭代器是一種特殊的對象,它具有一些專門為迭代過程設計的專有接口,所有的迭代器對象都有一個next()方法,每次調用都返回一個結果對…

    個人 2025年3月8日
    1.1K00
  • Node深入淺出(聖思園教育) 001【學習筆記】

    node 從異步編程範式理解 Node.js Node.js 的定位與核心思想 基於 V8 引擎 + libuv 事件驅動庫,將 JavaScript 從瀏覽器帶到服務器側。 採用單線程事件循環處理 I/O,最大化利用 CPU 等待 I/O 的時間片,特別適合高併發、I/O 密集型場景。 “不要阻塞主線程”是設計哲學:盡量把耗時操作交給內核或線程池,回調結果…

    個人 2025年11月24日
    27700
  • TS珠峰 001【學習筆記】

    課程大綱 搭建 TypeScript 開發環境。 掌握 TypeScript 的基礎類型,聯合類型和交叉類型。 詳細類型斷言的作用和用法。 掌握 TypeScript 中函數、類的類型聲明方式。 掌握類型別名、接口的作用和定義。 掌握泛型的應用場景,熟練應用泛型。 靈活運用條件類型、映射類型與內置類型。 創建和使用自定義類型。 理解命名空間、模塊的概念已經使…

    個人 2025年3月27日
    1.5K00
  • TS珠峰 002【學習筆記】

    泛型 /* * @Author: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git &a…

    個人 2025年3月27日
    1.5K00
  • 無畏前行,拳釋力量 🥊💪

    拼搏,是一種態度 生活就像一場比賽,沒有捷徑可走,只有不斷訓練、突破、超越,才能站上屬於自己的舞台。這不僅是一種對抗,更是一種自我的覺醒——敢於迎戰,敢於挑戰,敢於成為更強的自己。 運動中的拼搏精神 無論是拳擊、跑步,還是力量訓練,每一次出拳、每一次揮汗、每一次咬牙堅持,都是對身體與心靈的磨煉。拼搏不是單純的對抗,而是一種態度——面對挑戰,不退縮;面對失敗,…

    個人 2025年2月26日
    1.3K00
簡體中文 繁體中文 English
歡迎🌹 Coding never stops, keep learning! 💡💻 光臨🌹