參考文獻
一、promise的簡述
含義
- Promise是非同步程式設計的一種解決方案,比傳統的解決方案——回撥函式和事件——更合理和更強大。它由社群最早提出和實現,ES6將其寫進了語言標準,統一了用法,原生提供了Promise物件。
- 所謂Promise,簡單說就是一個容器,裡面儲存著某個未來才會結束的事件(通常是一個非同步操作)的結果。從語法上說,Promise 是一個物件,從它可以獲取非同步操作的訊息。Promise 提供統一的 API,各種非同步操作都可以用同樣的方法進行處理。
簡單說promise就是一個承諾,未來才會實現。比如媳婦等我有錢了給你買包, 先等著,給你個承諾,等有錢了再買。承諾就是一個等待態,你可以設定成功或者失敗,即買包和不買包,這就是下面所說的三個狀態了。
特點
- 物件的狀態不受外界影響。Promise物件代表一個非同步操作,有三種狀態:pending(進行中)、resolves(已成功)和rejected(已失敗)。
- 一旦狀態改變,就不會再變。只有兩種可能:從pending變為fulfilled和從pending變為rejected。
簡單說就是Promise物件有三種狀態,一旦成功就不能失敗,一旦失敗就不能成功
主要解決回撥地獄,函式巢狀的問題
- 比如看我們下面的程式碼
let fs = require("fs");
fs.readFile("a.txt",'utf8',function(data1){
fs.readFile("b.txt",'utf8',function(data2){
console.log(data1,data2);
})
})
複製程式碼
data2資料需要依賴上一次的返回結果data1時,就會造成巢狀問題,當無限巢狀下去,就會形成回撥地獄問題, 下面我們來看promise基礎用法,怎麼解決這類問題
二、promise的基礎用法
建立一個promise例項
- Promise本身是一個建構函式,需要我們new 一個例項,傳遞一個函式作為引數(我們稱之為執行器函式 executor),函式接收兩個引數 resolve(成功函式) 、reject(失敗函式)
let p =new Promise((resolve,reject)=>{
//執行器預設在new時就會被呼叫,立即執行
console.log("1")
resolve("123") //成功函式resolve,傳遞了123
});
複製程式碼
這有什麼用呢,我們來看p的then方法怎麼得到123
then鏈式寫法
- then中傳遞兩個函式,第一個函式對應成功時候回撥(即resolve('123')),第一個函式對應失敗時候回撥(即reject('123'))
- 這樣的話就把resolve('123')中的123,被then中成功回撥所捕獲 data就是123啦,如果傳遞reject('123')就會被失敗回撥捕獲
p.then(value=>{
//value指的上面resolve傳遞的引數,成功的原因
console.log(value)
},err=>{
//失敗的原因, reject傳遞的引數
console.log(err)
})
.then(value=>{
console.log(value)
},err=>{
console.log(err)
})
複製程式碼
- 回想下我們如何用promise解決上述巢狀問題
let fs = require('fs');
function read(file){
return new Promise(function(resolve,reject){
fs.readFile(file,'utf8',function(err,data){
if (err) {
return reject(err);
}
resolve(data);
})
})
}
read('./a.txt').then(function(data){
return read('./b.txt');
}).then(function(data){
console.log(data);
})
複製程式碼
- 上述的寫法是不是更具有流程感
- then還可以穿透,什麼意思呢,直接上程式碼
let Promise = require('./Promise');
let promise = new Promise((resolve,reject)=>{
resolve('hello');
});
promise.then().then().then(data=>{ //可以無限的then,但結果仍會拿到
console.log(data); //'hello'
},err=>{
console.log('err',err);
})
複製程式碼
錯誤處理catch
- catch捕獲錯誤,與try/catch語句有類似的功能,可以把then第二個引數省去,在最後面寫上.catch
p.then().then().catch(err=>{
console.log(err)
})
複製程式碼
Promise.all()
- Proise.all()在所有的非同步操作執行完後才執行的回撥,接受一個陣列,陣列中每項都應是一個promise例項,Promise.all()返回的結果也是一個promise,因此也可以.then下去,上一段程式碼吧
let fs = require("fs");
function read(path) {
return new Promise((resolve, reject) => {
fs.readFile(path, 'utf8', function(err, data) {
if (err) return reject(err);
resolve(data);
});
});
}
Promise.all([read("1.txt"), read("2.txt")]).then( //可以then說明Promise.all()返回結果也是promise
data => {
console.log(data);// [1.txt內容,2.txt內容]
},
err => {
console.log(err);
}
);
複製程式碼
Promise.race()
- 用法跟Promise.all()很像,指的是誰跑得快,執行誰的回撥。
let fs = require("fs");
function read(path) {
return new Promise((resolve, reject) => {
fs.readFile(path, 'utf8', function(err, data) {
if (err) return reject(err);
resolve(data);
});
});
}
Promise.all([read("1.txt"), read("2.txt")]).then( //可以then說明Promise.all()返回結果也是promise
data => {
console.log(data);// [1.txt或者2.txt內容]
},
err => {
console.log(err);
}
);
複製程式碼
讀到這裡,相信大家看到這裡都應該大概對promise有一定的瞭解,下一章帶領大家手寫一套符合promise A+規範的程式碼。