一. promise是什麼
簡單來說是一種非同步流程的控制手段
-
所謂Promise ,簡單說就是一個容器,裡面儲存著某個未來才會結束的事件(通常是一個非同步操作)的結果。從語法上說,Promise是一個物件,從它可以獲取非同步操作的訊息。Promise 物件的狀態不受外界影響
-
在JavaScript的世界中,所有程式碼都是單執行緒執行的。 由於這個“缺陷”,導致JavaScript的所有網路操作,瀏覽器事件,都必須是非同步執行。
非同步執行容易造成回撥地獄
例如:
$.ajax( success(){ $.ajax( success(){ } ) } ) 複製程式碼
使用promise的鏈式呼叫就可以很好的解決這個問題
例如:vue-resource
this.$http.post(url,parms).then(res => { console.log(res) },err => { }).then(res=>{ },err=>{ }) 複製程式碼
二.promise的使用及方法
ES6規定,Promise物件是一個建構函式,用來生成Promise例項。Promise本身有all、race、reject、resolve這幾個方法
- Promise只有一個引數 叫excutor執行器,預設new時就會呼叫
let p = new Promise((resolve,reject)=>{ // 預設promise中的executor是同步執行的 resolve('買'); }); // then方法是非同步呼叫的,事件環 p.then((value)=>{ // value成功的原因 console.log(value);//買 },(err)=>{ // err失敗的原因 }); 複製程式碼
注意:then方法是Promise例項上的方法
-
Promise的reject、resolve方法
promise有三種狀態:resolve 成功 reject 失敗 pending 等待態。 如果一旦promise成功了就不能失敗,相反也是一樣的,只有狀態是等待的狀態時才可以轉化狀態。pending->reject(resolve)
1.Promise.resolve() 返回一個成功的promise
2.Promise.reject() 返回一個失敗的promise
例:
let fs = require('fs'); // fileSystem function read(url) { return new Promise((resolve, reject) => { fs.readFile(url, 'utf8', function (err, data) { if (err) reject(err);//成功返回 resolve(data);//失敗返回 }) }) } 複製程式碼
-
Promise的all、race方法
promise可以支援多個併發的請求,獲取併發請求中的資料
1.Promise.all
這可能是個很有用的方法,它可以統一處理多個Promise。Promise.all能將多個Promise例項包裝成一個Promse例項
let Promise1 = new Promise(function(resolve, reject){}) let Promise2 = new Promise(function(resolve, reject){}) let Promise3 = new Promise(function(resolve, reject){}) let p = Promise.all([Promise1, Promise2, Promise3]) p.then(funciton(){ // 三個都成功則成功 }, function(){ // 只要有失敗,則失敗 }) 複製程式碼
2.Promise.race()
與all方法類似,也可以將多個Promise例項包裝成一個新的Promise例項 不同的是,all時大Promise的狀態由多個小Promise共同決定,而race時由第一個轉變狀態的小Promise的狀態決定,第一個是成功態,則轉成功態,第一個失敗態,則轉失敗態。
** 簡單來說就是賽跑,處理多請求只取最快的 **
let fs = require('fs'); // fileSystem function read(url) { return new Promise((resolve, reject) => { fs.readFile(url, 'utf8', function (err, data) { if (err) reject(err);//成功返回 resolve(data);//失敗返回 }) }) } Promise.race([read('1.txt'),read('2.txt')]).then((data)=>{ console.log(data);//最快讀取完成功則成功 },err=>{ console.log(err);//最快讀取完失敗則失敗 }); 複製程式碼
三. promise的簡單實現
通過上文我們已經知道Promise是一個建構函式,我們可以使用ES6的class類來建立一個Promise
下面我們建立一個class類來完成promise的then、reject、resolve方法
class Promise {
constructor(executor) {
// 預設狀態是等待態
this.status = 'pending';
this.value = undefined;
this.reason = undefined;
// 存放成功的回撥
this.onResolvedCallbacks = [];
// 存放失敗的回撥
this.onRejectedCallbacks = [];
let resolve = (data) => {
if (this.status === 'pending') {
this.value = data;
this.status = 'resolved';
this.onResolvedCallbacks.forEach(fn => fn());
}
}
let reject = (reason) => {
if (this.status === 'pending') {
this.reason = reason;
this.status = 'rejected';
this.onRejectedCallbacks.forEach(fn => fn());
}
}
try { // 執行時可能會發生異常
executor(resolve, reject);
} catch (e) {
reject(e); // promise失敗了
}
}
then(onFulFilled, onRejected) {
if (this.status === 'resolved') {
onFulFilled(this.value);
}
if (this.status === 'rejected') {
onRejected(this.reason);
}
// 當前既沒有完成 也沒有失敗
if (this.status === 'pending') {
// 存放成功的回撥
this.onResolvedCallbacks.push(() => {
onFulFilled(this.value);
});
// 存放失敗的回撥
this.onRejectedCallbacks.push(() => {
onRejected(this.reason);
});
}
}
}
module.exports = Promise;
複製程式碼
完成了基本的功能,我們可以使用自己寫的promise來測試一下
let Promise = require('./promise');//引入
let p = new Promise((resolve,reject)=>{
resolve(123);
reject(123);
});
p.then((data)=>{
console.log('s',data);//s,123
},(err)=>{
console.log('e',err);//e,123
});
複製程式碼
總結:
-
Promise是一種非同步流程的控制手段
-
每一個promise的例項上都有一個then方法,then方法中有兩個引數,一個引數叫成功的函式 ,一個是失敗的函式
-
Promise可以鏈式呼叫,並且可以支援多個併發的請求,獲取併發請求中的資料
-
如果一旦promise成功了就不能失敗,相反也是一樣的。只有狀態是等待的狀態時 才可以轉化狀態
-
Promise可以解決非同步的問題,但不能說promise本身是非同步的