1. 什么是 Promise?
Promise 是 JavaScript 中處理異步操作的一種機制,它可以讓異步操作更加容易管理和控制。Promise 對象代表一個異步操作的最終完成或失敗,并提供了一種方式來處理操作的結果。
2. Promise 的基本語法
Promise 對象有三種狀態:
- Pending(進行中):初始狀態,既不是成功,也不是失敗。
- Fulfilled(成功):操作成功完成。
- Rejected(失敗):操作失敗。
改變Promise狀態:Promise對象的狀態改變,只有兩種可能:從pending變為fulfilled和從pending變為rejected。狀態一旦改變,就不會再變,也就是說,Promise對象的狀態改變是單向的。
Promise 的基本語法如下:
// 實例化promise對象
const promise = new Promise((resolve, reject) => {// 異步操作if (/* 異步操作成功 */) {resolve(value); // 將Promise對象的狀態從“pending”變為“fulfilled”,同時將異步操作的結果,作為回調函數的參數} else {reject(reason); // 將Promise對象的狀態從“pending”變為“rejected”,同時將異步操作報出的錯誤,作為回調函數的參數}
});promise.then(value => {// 成功時的回調函數,即當Promise的狀態變為fulfilled時調用
}, reason => {// 失敗時的回調函數,即當Promise的狀態變為rejected時調用
});// 例如:
//實例化 Promise 對象
const p = new Promise(function(resolve, reject){setTimeout(function(){//// let data = '數據庫中的用戶數據';// resolve// resolve(data);let err = '數據讀取失敗';reject(err);}, 1000);
});//調用 promise 對象的 then 方法
p.then(function(value){console.log(value);
}, function(reason){console.error(reason);
})
3.Promise的then方法
const p =new Promise((resolve, reject) =>{setTimeout(()=>{resolve('用戶數據');})
});//then()函數返回的實際也是一個Promise對象
//1.當回調后,返回的是非Promise類型的屬性時,狀態為fulfilled,then()函數的返回值為對象的成功值,如reutnr 123,返回的Promise對象值為123,如果沒有返回值,是undefined//2.當回調后,返回的是Promise類型的對象時,then()函數的返回值為這個Promise對象的狀態值//3.當回調后,如果拋出的異常,則then()函數的返回值狀態也是rejected
let result = p.then(value => {console.log(value)// return 123;// return new Promise((resolve, reject) => {// resolve('ok')// })throw 123
},reason => {console.log(reason)
})
console.log(result);
4. Promise的catch方法
catch()
函數只有一個回調函數,意味著如果Promise對象狀態為失敗就會調用catch()方法并且調用回調函數
const p = new Promise((resolve, reject)=>{setTimeout(()=>{//設置 p 對象的狀態為失敗, 并設置失敗的值reject("出錯啦!");}, 1000)
});// p.then(function(value){}, function(reason){
// console.error(reason);
// });p.catch(function(reason){console.warn(reason);
});
5. Promise 的實踐
5.1 讀取單個文件
使用 Promise 封裝讀取文件的操作:
// 引入 fs 模塊
const fs = require('fs');// 使用 Promise 封裝
const p = new Promise(function(resolve, reject){fs.readFile("./resources/為學.md", (err, data)=>{// 判斷如果失敗if(err) reject(err);// 如果成功resolve(data);});
});p.then(function(value){console.log(value.toString());
}, function(reason){console.log("讀取失敗!!");
});
5.2 讀取多個文件
使用 Promise 鏈式調用讀取多個文件:
// 引入 fs 模塊
const fs = require("fs");// 使用 promise 實現
const p = new Promise((resolve, reject) => {fs.readFile("./resources/為學.md", (err, data) => {resolve(data);});
});p.then(value => {return new Promise((resolve, reject) => {fs.readFile("./resources/插秧詩.md", (err, data) => {resolve([value, data]);});});
}).then(value => {return new Promise((resolve, reject) => {fs.readFile("./resources/觀書有感.md", (err, data) => {// 壓入value.push(data);resolve(value);});})
}).then(value => {console.log(value.join('\r\n'));
});
6.promise封裝Ajax
function ajax(url) {return new Promise((resolve, reject) => {const xhr = new XMLHttpRequest();xhr.open('GET', url);xhr.onreadystatechange = function() {if (xhr.readyState === 4) {if (xhr.status >= 200 && xhr.status < 300) {resolve(xhr.responseText);} else {reject(new Error(xhr.statusText));}}};xhr.send();});
}// 使用封裝好的函數發送 AJAX 請求
ajax('https://api.example.com/data').then(data => {console.log(data);}).catch(error => {console.error(error);});
7. Promise.all()
Promise.all
方法用于將多個 Promise 實例,包裝成一個新的 Promise 實例。
let promise1 = Promise.resolve(3);
let promise2 = 42;
let promise3 = new Promise((resolve, reject) => {setTimeout(resolve, 100, 'foo');
});Promise.all([promise1, promise2, promise3]).then((values) => {console.log(values);
});
// 輸出: [3, 42, "foo"]
8. Promise.race
Promise.race
方法用于將多個 Promise 實例,包裝成一個新的 Promise 實例,并以數組中,第一個完成的 Promise 實例的結果值,作為返回結果。
let promise1 = new Promise((resolve, reject) => {setTimeout(resolve, 500, 'one');
});let promise2 = new Promise((resolve, reject) => {setTimeout(resolve, 100, 'two');
});Promise.race([promise1, promise2]).then((value) => {console.log(value);// "two" —— 因為它比 promise1 完成得快
});
9. 總結
Promise 是 JavaScript 中處理異步操作的一種強大機制,它可以讓異步操作更加容易管理和控制。通過封裝異步操作,可以避免回調地獄,使代碼更加清晰和易于維護。