91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何在ES6中使用promise 和async函數

發布時間:2021-03-17 14:50:35 來源:億速云 閱讀:261 作者:Leah 欄目:web開發

如何在ES6中使用promise 和async函數?針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

promise 基本用法

Promise 對象是一個構造函數,用來生成 Promise 實例。Promise 構造函數接受一個函數作為參數,該函數的兩個參數分別是 resolve 和 reject。

resolve 函數的作用是,在異步操作成功時調用(Promise 對象的狀態從 pending 變為 fulfilled),并將異步操作的結果,作為參數傳遞出去。

reject 函數的作用是,在異步操作失敗時調用(Promise對象的狀態從 pending 變為 rejected),并將異步操作報出的錯誤,作為參數傳遞出去。

const funPromise = function(options) {
 return new Promise(function(resolve, reject) {
  if (/* 異步操作成功 */){
   resolve(result);
  } else {
   reject(error);
  }
 });
}

resolve 函數的參數除了正常的值以外,還可能是另一個 Promise 實例,此時,初始 promise 的最終狀態根據傳入的新的 Promise 實例決定。

reject 方法的作用,相當于拋出錯誤。等同于 throw new Error('error')。

Promise.prototype.then()

Promise 實例具有 then 方法,它的作用是為 Promise 實例添加狀態改變時的回調函數,即 Promise 實例生成以后,用 then 方法分別指定 fulfilled 狀態和 rejected 狀態的回調函數。

funPromise().then(function(result) {
 // fulfilled
}, function(error) {
 // rejected
})

then 方法可以接受兩個回調函數作為參數。第一個回調函數是 Promise 對象的狀態變為 fulfilled 時調用,第二個回調函數是 Promise 對象的狀態變為 rejected 時調用。其中,第二個函數是可選的,不一定要提供。這兩個函數都接受 Promise 對象傳出的值作為參數。

then 方法返回的是一個新的 Promise 實例(注意,不是原來那個 Promise 實例)。因此可以采用鏈式寫法,即 then 方法后面再調用另一個 then 方法來處理上一個 then 方法中 return 的結果。

funPromise().then(function(result) {
 return result.data;
}).then(function(data) {
 // fulfilled
});

上面的代碼使用 then 方法,依次指定了兩個回調函數。第一個回調函數完成以后,會將返回結果作為參數,傳入第二個回調函數。并且,第一個 then 返回的結果也可以是另一個異步操作的 Promise 對象,這時后一個 then 函數,就會等待該 Promise 對象的狀態發生變化,才會被調用。

funPromise().then(
 (result) => { return funPromise(result); }
).then(
 (data) => { /* fulfilled */ },
 (error) => { /* rejected */ }
);

上面代碼中,第一個 then 方法指定的回調函數,返回的是另一個 Promise 對象。這時,第二個 then 方法指定的回調函數,就會等待這個新的 Promise 對象狀態發生變化。如果變為 fulfilled,就調用第一個回調函數,如果狀態變為 rejected,就調用第二個回調函數。

Promise.prototype.catch()

Promise 實例具有 catch 方法,它的作用是為 Promise 實例添加狀態改變為 rejected 狀態的回調函數,也就是 then 方法的第二個函數的替代寫法。

funPromise().then(function(result) {
 // fulfilled
}).catch(function(error) {
 // 處理 funPromise 和之前 then 回調函數運行時發生的錯誤
});

Promise 對象的錯誤具有“冒泡”性質,會一直向后傳遞,直到被捕獲為止。也就是說,無論前面有多少個 then 函數,其中的錯誤總是會被下一個 catch 語句捕獲。

funPromise().then(function(result) {
 return funPromise(result);
}).then(function(data) {
 // fulfilled
}).catch(function(error) {
 // 處理前面三個 Promise 產生的錯誤
});

一般來說,不要在 then 方法里面定義 rejected 狀態的回調函數(即 then 的第二個參數),總是使用 catch 方法,因為這種寫法可以捕獲前面 then 方法執行中的錯誤。

catch 方法返回的還是一個 Promise 對象,并且 catch 中如果沒有拋出任何其它錯誤,那么該 Promise 對象則是 resolved 狀態。而且后面還可以接著調用 then 方法,但是前面的 catch 不能捕獲后面的 then 中的錯誤,所以盡量 catch 都寫在最后。

Promise.all()

Promise.all() 方法用于將多個 Promise 實例,包裝成一個新的 Promise 實例。其接受一個數組作為參數,數組中的值都是 Promise 實例,如果不是,就會先調用 Promise.resolve() 方法,將參數轉為 Promise 實例,再進一步處理。

const p = Promise.all([funPromise(1), funPromise(2), funPromise(3)]);

p 的狀態由數組中的值決定,分成兩種情況。

  • 數組中 Primise 實例的狀態都變成 fulfilled,p 的狀態才會變成 fulfilled,此時數組中實例的返回值組成一個數組,傳遞給 p 的回調函數。

  • 只要數組的實例之中有一個被 rejected,p 的狀態就變成 rejected,此時第一個被 reject 的實例的返回值,也就是報錯信息,會傳遞給 p 的回調函數。

p.then(function (results) {
 // 全部 fulfilled,results 是個數組,里面是每個實例的返回結果
}).catch(function(error){
 // 其中有一個變為 rejected
});

注意,如果作為參數的 Promise 實例,自己定義了 catch 方法,那么它一旦被 rejected,并不會觸發 Promise.all() 的 catch 方法。

應用

用 Promise 對象實現 Ajax。

const getAjax = function(url) {
 const promise = new Promise(function(resolve, reject){
  const handler = function() {
   if (this.readyState === 4 && this.status === 200) {
    resolve(this.response);
   } else {
    reject(new Error(this.statusText));
   }
  };
  const xhr = new XMLHttpRequest();
  xhr.open("GET", url);
  xhr.onreadystatechange = handler;
  xhr.responseType = "json";
  xhr.setRequestHeader("Accept", "application/json");
  xhr.send();
 });
 return promise;
};

getAjax("/test.json").then(function(json) {
 console.log('Contents: ' + json);
}, function(error) {
 console.error('出錯了', error);
});

async / await 基本用法

當 async 函數執行的時候,一旦遇到 await 就會先等到 await 后的異步操作完成,再接著執行函數體內之后的語句。

async 函數返回一個 Promise 對象,可以使用 then 方法添加回調函數。async 函數內部 return 語句返回的值,會成為 then 方法回調函數的參數。

async function f() {
 return 'hello dora';
}

f().then(v => console.log(v))  // "hello dora"

async 函數內部拋出錯誤,會導致返回的 Promise 對象變為 rejected 狀態。拋出的錯誤對象會被 catch 方法回調函數接收到。

async function f() {
 throw new Error('出錯了');
}

f().catch( e => console.log(e)) // Error: 出錯了

await 命令

正常情況下,await 命令后面是一個 Promise 對象,返回該對象的結果。如果不是 Promise 對象,就直接返回對應的值。

async function f() {
 return await 123;       // 等同于 return 123;
}

f().then(v => console.log(v)) // 123

await 命令后面的 Promise 對象如果變為 rejected 狀態,則錯誤會被 catch 方法的回調函數接收到。

任何一個 await 語句后面的 Promise 對象變為 rejected 狀態,那么整個 async 函數就會中斷執行。

有時,我們希望即使前一個異步操作失敗,也不要中斷后面的異步操作,有兩個解決辦法:

第一種方法是可以將 await 放在 try...catch 結構里面,這樣不管這個異步操作是否成功,后面的代碼都會執行。

async function f() {
 try {
  await Promise.reject('出錯了');
 } catch(e) { }
 return await Promise.resolve('hello dora');
}

f().then(v => console.log(v))  // hello dora

另一種方法是 await 后面的 Promise 對象再跟一個 catch 方法,處理前面可能出現的錯誤。

async function f() {
 await Promise.reject('出錯了').catch(e => console.log(e));
 return await Promise.resolve('hello dora');
}

f().then(v => console.log(v))
// 出錯了
// hello dora

使用注意點

1. 錯誤處理

前面已經說過,await 命令后面的 Promise 對象,運行結果可能是 rejected,所以防止出錯的方法,就是最好把 await 命令放在 try...catch 代碼塊中。如果有多個 await 命令,可以統一放在 try...catch 結構中,如果只有一個 await,可以使用上例中的 catch 捕獲 await 后面的 promise 拋出的錯誤。

const superagent = require('superagent');
const NUM_RETRIES = 3;

async function test() {
 let i;
 for (i = 0; i < NUM_RETRIES; i++) {
  try {
   await superagent.get('/api/xxx');
   break;
  } catch(err) {}
 }
}

test();

上面代碼中,使用 try...catch 結構,實現多次重復嘗試。如果 await 操作成功,就會使用 break 語句退出循環;如果失敗,會被 catch 語句捕捉,然后進入下一輪循環。

2. 多個 await 異步操作并發執行

多個 await 命令后面的異步操作,如果不存在繼發關系(即互不依賴),最好讓它們同時觸發,以縮短程序的執行時間。

// 寫法一
let [foo, bar] = await Promise.all([getFoo(), getBar()]);

// 寫法二
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;

3. forEach 等數組遍歷方法的參數為 async 函數時是并發執行的

只有 async 函數內部是繼發執行,外部不受影響,因此 forEach()、map() 等數組遍歷方法的參數改成 async 時是并發執行的。

function dbFuc() { //這里不需要 async
 let docs = [{}, {}, {}];

 // 會得到錯誤結果
 docs.forEach(async (doc)=> {
  await funPromise(doc);
 });
}

上面代碼會得到錯誤結果,原因是這時三個 funPromise(doc) 操作是并發執行的,也就是同時執行,而不是繼發執行。因此正確的寫法是采用 for 循環。

async function dbFuc() {
 let docs = [{}, {}, {}];

 for (let doc of docs) {
  await funPromise(doc);
 }
}

如果需要并發執行,可使用 Promise.all() 方法。

async function dbFuc() {
 let docs = [{}, {}, {}];
 let promises = docs.map((doc) => funPromise(doc));

 let results = await Promise.all(promises);
 return results;
}

有一組異步操作,需要按照順序完成。

async function logInOrder(urls) {
 // 并發讀取遠程URL
 const textPromises = urls.map(async url => {
  const response = await fetch(url);
  return response.text();
 });

 // 按次序輸出
 for (const textPromise of textPromises) {
  console.log(await textPromise);
 }
}

關于如何在ES6中使用promise 和async函數問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

奉新县| 龙州县| 乐亭县| 普陀区| 昭觉县| 刚察县| 柳江县| 清原| 句容市| 沙坪坝区| 清苑县| 焦作市| 儋州市| 青川县| 和硕县| 图木舒克市| 登封市| 孝感市| 麟游县| 拜城县| 墨玉县| 平昌县| 广州市| 临安市| 佛学| 类乌齐县| 西和县| 禹州市| 客服| 元阳县| 来宾市| 沂源县| 右玉县| 道真| 梁山县| 社会| 东阿县| 宜宾县| 政和县| 拉孜县| 桓仁|