JavaScript異步解決方案之Promise

概念

  • Promise 對象用於表示一個異步操做的最終完成或者失敗,以及結果值
  • Promise()是一個構造函數,用於實例化 Promise對象
  • Promise是一種新的寫法,而不是新的功能
  • 回調函數自己沒有問題,問題是多個回調函數嵌套,容易造成回調地獄,Promise就是爲了解決這個問題

語法

// 實例化一個Promise對象
new Promise(
  // excutor 執行器
  function(resolve,reject){}
)
// 使用函數包裹
function createPromise(...){
	return new Promise(
  	function(resolve,reject) ) } 複製代碼

語法解析

  • Promise構造函數的參數 是一個函數,稱爲執行器
  • Promis構造函數實例化對象時 會當即調用執行器函數(立刻執行 ,所以 Promise對象通常使用函數包裹)

執行器函數解析

參數

執行器函數接收兩個參數,resolve和reject。這兩個都是函數,由JS引擎提供 javascript

執行

執行器函數內一般會執行一些異步操做,一旦異步操做完成,能夠經過判斷,要麼調用resolve函數將Promise的狀態由pending改成fulfilled,或者調用reject將Promise的狀態修改成rejected html

錯誤

若是在執行器函數內拋出一個錯誤,那麼該promise的狀態就會變化rejected,執行器函數的返回值將被忽略。 java

Promise的狀態

Promise對象有三種狀態promise

  • pending 初始狀態
  • fulfilled  成功狀態
  • rejected 失敗狀態

pending狀態的Promise對象可能會變爲fulfilled狀態並傳遞一個值給相應的狀態處理方法。也能夠變爲失敗狀態並傳遞失敗信息。瀏覽器

屬性

  1. Promise.length length屬性,其值老是爲1
  2. Promise.prototype 表示Promise構造函數的原型

方法(由Promise調用)

Promise.resolve(value)

返回一個給定值解析後的Promise對象。(將參數轉化爲Promise對象)。 異步

返回值規則

  • 若是value爲基本類型的值,則返回一個resolved狀態的Promise,並將value做爲返回的Promise的第一個回調函數的參數。(做爲成功回調函數的參數)
  • 若是value爲Promise,則返回這個Promise。
  • 若是value爲thenable對象,(定義了then方法的對象),返回的Promise會緊隨這個對象,而且採用它的最終狀態。(疑問)

注意

不要在解析爲自身的thenable對象上調用Promise.resolve(),這將會致使無線遞歸。(有疑問)函數

Promise.reject(reason)

返回一個帶有拒絕緣由參數的Promise對象ui

Promise.reject("Testing static reject").then(
  function(reason) {
  // 成功時的回調函數未被調用
}, function(reason) {
  // 失敗時的回掉函數 執行了
  console.log(reason); // "Testing static reject"
});

複製代碼

Promise.all(iterable)

Promise.race(iterable)

原型屬性

原型屬性是指Promise.prototype上的屬性,即每一個實例的公有屬性。spa

  • Promise.prototype.constructor  返回被建立的實例的構造函數,默認爲Promise()

原型方法

Promise.prototype.then(onFulfilled,onRejected)

參數

最多須要兩個參數,Promise狀態變爲成功時的回調函數以及狀態變爲失敗時的回調函數。 prototype

參數省略的狀況

若是忽略針對某個狀態的回調函數參數,或者提供非函數參數,那麼then方法將會丟失關於該狀態的回調函數信息,可是並不會產生錯誤。
若是調用then方法的Promise狀態發生變化,可是then方法中沒有關於這種狀態的回調函數,那麼then方法將自動建立一個沒有通過回調函數處理的新Promise對象,這麼新的Promise的狀態就是原來的Promise的終態。(仔細理解)

var p = new Promise((resolve, reject) => {
    resolve('foo')
})
// 'bar'不是函數,會在內部替換爲 (x)=>x
p.then('bar').then((value)=>{
	console.log(value) //'foo'
})
複製代碼

參數解析

  • onFulfilled 當Promise狀態變成接受狀態時,該參數做爲回調函數被調用。該函數有一個參數,即接受的最終結果。
  • onRejected 當Promise變成拒絕狀態,該參數做爲回調函數被調用。該函數有一個參數,即拒絕的緣由。

返回值

返回值存在如下幾種狀況:

  • 返回一個值
  • 不返回值
  • 返回一個Promise
    • 返回一個完成狀態的Promise
    • 返回一個拒絕狀態的Promise
    • 返回pengding狀態的Promise

具體分析以下:

  1. 若是then中的回調函數返回一個值,那麼then中返回 的promise會變成接受狀態,而且將返回的值做爲接受狀態的回調函數的的參數值。
// 實例化一個Promise對象
var p = new Promise((resolve,reject)=>{ resolve('foo')})
// 首先 resolve函數 能夠向回調函數傳遞一個值,經過resolve(value)的方式
p.then((value)=>{
	return 'xhb' // then中的回調函數返回 return一個值
})
// 首先 咱們知道 then方法 會返回一個Promise對象
// 根據規則,若是在then中的回調函數中返回一個值, 會將整個then方法返回的promise的狀態變爲成功狀態
// 而且 咱們在上一個promise return的值,會做爲下一個promise的then方法中第一個回調函數(完成狀態的
//的回調函數)的參數,便可以在完成狀態的回調函數接受到這個值,咱們能夠打印一下
p.then((value)=>{
	return 'xhb'
}).then(value => {
	console.log(value)
})

複製代碼

在瀏覽器中運行以下:

  1. 若是then中回調函數沒有返回值,那麼then方法返回的Promise狀態會變成接受狀態,而且這個promise的第一個回調函數(成功狀態的回調)會接受一個undefined的參數

具體分析以下:

// 實例化一個Promise
var p = new Promise((resolve,reject)=>{ resolve("foo")})

p.then((value)=>{
  console.log(value) // 打印參數 這裏並無返回值 
  // 根據規則,then方法就會返回一個resolved狀態的promise,而且接收一個值爲undefinde的參數
}).then(
  function(value){
    // 接收一個值爲undefined的參數
    console.log(value) // undefined
  }
)

複製代碼

在瀏覽器中運行以下:

  1. 若是then方法中的回調函數拋出一個錯誤,那麼then方法將返回一個rejected狀態的Promise,而且拋出的錯誤將做爲這個Promise的第二個回調函數(拒絕狀態的回調函數)的參數。
  2. 返回一個resolved狀態的Promise,若是then中的回調函數返回一個已是成功接受狀態的Promise,那麼then中返回的Promise也是成功狀態,而且將那個Promise的接受狀態的回調函數參數值做爲then方法返回的Promise的接受狀態的回調函數的參數(成功狀態的回調函數的參數 會傳遞)

具體分析以下:

// 實例化一個Promise
var p = new Promise({(resolve,reject)=>{ resolve('foo')})
// 返回一個成功狀態的Promise
// ? 調用構造函數 實例化Promise的時候,就已經執行了執行器函數,
p.then(()=>return new Promise((resolve)=>{ resolve('return PromiseValue')})
複製代碼

在瀏覽器中運行

Promise.prototype.catch(onRejected)

catch方法返回一個Promise,而且處理拒絕的狀況。它的行爲與調用Promise.prototype.then()。

參數
  • OnReject   當Promise被rejected時,被調用的一個Funtion。該函數擁有一個參數:
    • reason rejection的緣由
    • 若是 onRejected拋出一個錯誤或返回一個自己失敗的Promise,經過catch()返回的Promise被rejected,不然,它將顯示爲成功。

Promise.prototype.finally(onFinally)

finally()方法返回一個Promise。在Promise結束時,不管結果是fulfilled,或者是rejected,都會執行執行的回調函數。
這避免一樣的語句須要在then方法和catch方法中各寫一次。

建立Promise

Promise對象是由關鍵字new及其構造函數來建立的。
該構造函數會把一個叫作處理器的函數做爲它的參數。
處理器函數接受兩個函數resolve和reject做爲它的參數。
當異步任務順利完成且返回結果值的時候,會調用resolve函數。
而當異步任務失敗且返回失敗緣由時,會調用reject函數。

實例

//使用Promise 完成讀取文件
const fs = require('fs')
// 實例化一個promise對象
const readFilePromise = function(fileName){
	return new Promise((resolve,reject)=>{
  	fs.readFile(fileName,'utf-8',(err,data)=>{
    	if(err) reject(err)
        resolve(data)
    })
    
  })
}
const p1 = readFilePromise('./index.html')
p1.then((data)=>{
    console.log(data)
}).catch(err=>{
    console.log(err)
})

複製代碼
相關文章
相關標籤/搜索