Promise複習

這是我參與8月更文挑戰的第2天,活動詳情查看:8月更文挑戰前端

複習Promise知識,關於它的概念,使用方式等,還有注意事項。 參考依然是阮一峯老師的 ESCMAScript6入門 es6.ruanyifeng.com/ ,寫它的緣由是在項目中能常常的使用到Promise作異步處理,,但對它並無系統性的瞭解。vue

Promise對象

概念

簡單說下,Promise是一種js單線程的異步處理方案,在對後端的接口請求中咱們常常會用到,相信大多數前端都對這個不陌生。ES6將Promise進行來便準規範。es6

狀態

promise有三種狀態,而且具有了狀態不受干擾以及狀態一旦改變就不會再變的特性。正則表達式

三種狀態分別是mongodb

  1. pending進行中
  2. fulfilled已成功
  3. rejected已失敗

須要注意的是,一旦執行,中途就沒法取消,若是不設置回調函數,Promise內部會拋出錯誤,並且在pending狀態中,不知道會進展到哪一個階段。後端

使用方式

在前端的使用過程當中,通常在請求的時候都會用到,有的用來封裝請求,也有在store中使用,固然也是封裝請求的。大體以下api

function getUserInfo(data) {
  return new Promise((resolve, reject) => {
    // 接口的方法
    if(true) {
      resolve('返回參數')
    } else {
      reject('錯誤的信息')
    }
  })
}
getUserInfo(data).then(res => {
  console.log(res)
}).catch(res => {
  console.log(res)
})

複製代碼

這個應該是最多見的使用方式,還有就是Promise.all()的方式,會在後邊寫到。數組

下邊一個異步加載圖片的例子promise

function loadImageAsync(url) {
  return new Promise((resolve, reject) => {
    const image = new Image()
    image.onload = function() {
      resolve(image)
    }
    image.onerror = function() {
      reject(new Error('Could not load image at '+ url))
    }
    image.src = url
  })
}
複製代碼

這裏比較重要的一點仍是promise的已成功 和已失敗兩個回調,在獲得圖片路徑的時候,使用resolve來返回正確的地址,錯誤的時候返回錯誤的地址。markdown

執行過程

在promise中,通常是從進行中到已成功或已失敗。在這個過程當中是有回調地址的,若是當前回調地址爲一個新的promise,那麼當前這個promise的狀態實際上是取決於當前回調這個promise的狀態的。

例如:

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve('p1'), 3000)
})
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => resolve(p1), 1000)
})
p2.then(result => console.log(result,'result')) // p1 result
  .catch(error => console.log(error,'error'))
複製代碼

當前這個例子彷佛是看不出來的,p2是成功回調,p1也是成功回調。對比第二個例子就能清晰看出來了

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => reject(new Error('錯了')), 3000)
})
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => resolve(p1), 1000)
})
p2.then(result => console.log(result,'result'))
  .catch(error => console.log(error,'error')) // Error: 錯了
複製代碼

兩個比較,咱們就能夠清晰認識到這一點。

then()和catch()

Promise 實例具備then方法,then方法是定義在原型對象Promise.prototype上的。then方法能夠鏈式調用,通俗說就是葫蘆娃救爺爺,一個接一個。

一樣,promise.prototype上還有catch,上一個是處理回調的,這個是用來處理錯誤的。

兩種等價的寫法

// 寫法一
const promise = new Promise(function(resolve, reject) {
  try {
    throw new Error('test');
  } catch(e) {
    reject(e);
  }
});
promise.catch(function(error) {
  console.log(error);
});

// 寫法二
const promise = new Promise(function(resolve, reject) {
  reject(new Error('test'));
});
promise.catch(function(error) {
  console.log(error);
});
// 比較上面兩種寫法,能夠發現reject()方法的做用,等同於拋出錯誤。
複製代碼

並且Promise 對象的錯誤會一直向後傳遞,直到被捕獲

finally

finally()方法用於指定無論 Promise 對象最後狀態如何,都會執行的操做。該方法是 ES2018 引入標準的。相對用的比較少,在特定環境下,finally 也會有奇效,具體看業務場景。

all()

Promise.all()方法用於將多個 Promise 實例,包裝成一個新的 Promise 實例。

這個方法,在nuxtjs作服務端渲染的時候會用的比較多一些。用的方式也很特別。打包一塊兒搞,所有返回後才走then方法。 狀態有兩種:所有爲fulfilled,狀態就是fuifilled;若是有一個是rejected,那麼狀態就爲rejected.

所有爲fulfilled

const p1 = new Promise((resolve, reject) => {
  resolve('p1');
})
.then(result => result)
.catch(e => e);

const p2 = new Promise((resolve, reject) => {
  resolve('p2');
})
.then(result => result)
.catch(e => e);

Promise.all([p1, p2])
.then(result => console.log(result,'then')) // ["p1", "p2"] "then"
.catch(e => console.log(e,'catch'));
複製代碼

有一個是rejected

const p1 = new Promise((resolve, reject) => {
  resolve('p1');
})
.then(result => result)
.catch(e => e);

const p2 = new Promise((resolve, reject) => {
  throw new Error('報錯了');
})
.then(result => result)
.catch(e => e);

Promise.all([p1, p2])
.then(result => console.log(result,'then'))
.catch(e => console.log(e,'catch'));
複製代碼

image.png

再看下面的例子

const p1 = new Promise((resolve, reject) => {
  resolve('p1');
})
.then(result => result)
.catch(e => e);

const p2 = new Promise((resolve, reject) => {
  throw new Error('報錯了');
})
.then(result => result)
.catch(e => e);

Promise.all([p1, p2])
.then(result => console.log(result,'then')) 
.catch(e => console.log(e,'catch'));
複製代碼

image.png

這個彷佛咱們以前所說的不一致,主要是由於p2中使用了catch, p2首先進入rejected,可是由於有本身的catch方法,方法會返回一個新的實例,p2指向的實際是這個實例。實例執行完成後也變爲了resolved,所以p1,p2都進入了then方法。

race()

這個方法和all()相反,那個率先改變的 Promise 實例的返回值,就傳遞給回調函數

const p1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 1000, 'p1')
})
.then(result => result)
.catch(e => e);

const p2 = new Promise((resolve, reject) => {
  resolve('p2');
})
.then(result => result)
.catch(e => e);

Promise.race([p1, p2])
.then(result => console.log(result,'then')) // p2 then
.catch(e => console.log(e,'catch'));
複製代碼

若是將定時器去掉,你會發現一直執行的都是p1

allSettled()

Promise.allSettled()方法接受一組 Promise 實例做爲參數,包裝成一個新的 Promise 實例。只有等到全部這些參數實例都返回結果,不論是fulfilled仍是rejected,包裝實例纔會結束。該方法返回的實例,狀態老是fulfilled,不會變成rejected,接受的參數也是一個數組。

const promises = [
  fetch('/api-1'),
  fetch('/api-2'),
  fetch('/api-3'),
];

await Promise.allSettled(promises);
removeLoadingIndicator();
複製代碼

any()

該方法接受一組 Promise 實例做爲參數,包裝成一個新的 Promise 實例返回。

Promise.any([
  fetch('https://v8.dev/').then(() => 'home'),
  fetch('https://v8.dev/blog').then(() => 'blog'),
  fetch('https://v8.dev/docs').then(() => 'docs')
]).then((first) => {  // 只要有一個 fetch() 請求成功
  console.log(first);
}).catch((error) => { // 全部三個 fetch() 所有請求失敗
  console.log(error);
});
複製代碼

以上就是回顧的全部知識點,有不足指出,還請多多指教!!!

相關文章

let,const複習 juejin.cn/post/699147…

初學koa搭建項目 juejin.cn/post/698756…

正則表達式總結 juejin.cn/post/698615…

flex佈局總結 juejin.cn/post/698497…

mongodb基礎用法 juejin.cn/post/698364…

vue3搭建管理後臺-項目搭建 juejin.cn/post/696802…

工廠模式,構造器模式和原型模式 juejin.cn/post/695794…

相關文章
相關標籤/搜索