一、Promise基本概念
Promise 是異步編程的一種解決方案,用於處理異步操作。ES6 的 Promise 規範,是對異步編程的一種規範化,使得編寫和維護異步程序更加容易、直觀。
Promise 是一個對象,它代表了一個異步操作的最終結果。它可以是下列三種狀態之一:等待態(pending)、完成態(fulfilled)、拒絕態(rejected)。
Promise 的優點在於可以避免「回調地獄」,使得代碼結構清晰,更具有可讀性和可維護性。
二、Promise基本用法
ES6 新增了 `Promise` 構造函數,可以使用 `new Promise()` 來創建一個 Promise 對象。
let promise = new Promise(function(resolve, reject){
//異步操作的代碼
//成功時調用 resolve()
//失敗時調用 reject()
})
當 Promise 對象的狀態發生改變時,會產生對應的回調函數。可以使用 `promise.then()` 方法來指定 Promise 對象狀態變為 fulfilled 或 rejected 時調用的回調函數。這兩個方法都返回一個新的 Promise 對象,可以進行鏈式調用。
let promise = new Promise(function(resolve, reject){
setTimeout(() => resolve("異步操作成功"), 1000);
})
promise.then(res => {
console.log(res); //異步操作成功
})
三、Promise原理
Promise 的基本原理就是對異步操作進行封裝,使其可以返回一個 Promise 對象,並可以使用鏈式調用方法。
我們可以手動模擬一下 Promise 的內部實現:
function Promise_old(fn){
let state = 'pending';
let value = null;
let callbacks = [];
this.then = function(onFulfilled){
return new Promise_old(function(resolve){
handle({
onFulfilled: onFulfilled || null,
resolve: resolve
})
})
}
function handle(callback){
if(state === 'pending'){
callbacks.push(callback);
return;
}
if(!callback.onFulfilled){
callback.resolve(value);
return;
}
let ret = callback.onFulfilled(value);
callback.resolve(ret);
}
function resolve(newValue){
if(newValue && (typeof newValue === 'object' || typeof newValue === 'function')){
let then = newValue.then;
if(typeof then === 'function'){
then.call(newValue, resolve);
return;
}
}
setTimeout(function(){
state = 'fulfilled';
value = newValue;
callbacks.forEach(function(callback){
handle(callback);
})
}, 0);
}
fn(resolve);
}
上述代碼中,我們定義了 `Promise_old` 構造函數。它內部定義了 `state`、`value`、`callbacks` 三個變量,分別記錄 Promise 對象的當前狀態、結果值和對應回調函數數組。同時我們定義了 `then` 方法,可以使用鏈式調用,將傳入的回調函數壓入 `callbacks` 數組中。
關鍵的 `handle` 函數則利用了 JavaScript 的事件循環機制,當 Promise 對象的狀態從 `pending` 改變時,依次執行隊列中的回調函數。
最後通過 `resolve` 函數,可以修改 Promise 對象的狀態,觸發對應回調函數的執行。
四、Promise實例應用
1、串行異步任務的處理
使用 `Promise` 可以讓多個異步任務按順序執行,比如讀取多個文件,順序進行操作。這裡我們演示一個例子,讀取兩個文件,分別將其內容存放在一個數組中。
let fs = require('fs');
function readFile(filename){
return new Promise(function(resolve, reject){
fs.readFile(filename, 'utf8', function(err, data){
if(err){
reject(err);
return;
}
resolve(data);
})
})
}
Promise.all([
readFile('file1.txt'),
readFile('file2.txt')
]).then(function(dataArr){
console.log(dataArr); //[data1, data2]
})
2、並發異步任務的處理
有時候需要同時執行多個異步任務,可以使用 `Promise.all()` 方法,將返回值存放在數組中按順序返回。
let dataArr = [];
function fetchData(url){
return new Promise((resolve, reject) => {
fetch(url)
.then(res => res.json())
.then(data => {
dataArr.push(data);
resolve(data);
})
.catch(error => reject(error))
})
}
Promise.all([
fetchData('https://api.xxx.com/1'),
fetchData('https://api.xxx.com/2'),
fetchData('https://api.xxx.com/3')
]).then(() => {
console.log(dataArr); //[data1, data2, data3]
})
3、Promise異常處理
使用 `then()` 方法時,可以鏈式調用多個回調函數,並在其中任何一個回調函數中引發錯誤,就會被 `catch()` 方法捕獲。如果在 `then()` 方法中不使用回調函數,就必須在鏈頭使用 `catch()` 方法來進行異常處理。
function fetchData(){
return new Promise((resolve, reject) => {
//使用 Math.random() 模擬程序執行時出現錯誤
if(Math.random() > 0.5){
resolve('fetch data success');
} else {
reject('fetch data failed');
}
})
}
//這個方法捕獲了兩個 Promise 對象中的異常,並輸出錯誤信息
fetchData().then(res => {
console.log(res);
}).catch(error => {
console.log(error);
})
結束語
Promise 是異步編程的一種新規範,提高了代碼的可讀性、可維護性和穩定性。通過上述的介紹和實例,希望讀者能夠深入了解 Promise 的基本原理和使用方法,高效編寫異步代碼。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/154561.html