promise 是什麼
Promise 是為了解決非同步回撥問題,處理非同步回撥使得程式碼層次更加清晰,便於理解,更加容易維護
複製程式碼
首先我們簡單實用一個一下es6的promise 然後去簡單實現一下,用setTimeout 簡單的模擬非同步
function fn1(resolve,reject){
setTimeout(()=>{
console.log(1)
resolve(1);
})
}
new Promise(fn1).then((data)=>{
console.log('data:'+data); // data : 1
})
// 結果是先打出一個1 然後在打出 data: 1
複製程式碼
簡單的實現上邊程式碼的promise
- 首先Promise 是一個函式 有兩個引數 resolve 和 reject 一個成功的引數一個失敗的引數
- promise 有三個狀態 pending 等待態 fulfilled 成功態 rejected 失敗態
- 如果 函式沒有返回成功或者失敗 那麼 他一直就是等待態, 需要兩個陣列把函式存起來,等待他的狀態變化 再去執行相對的函式 設定兩個陣列 一個為 成功的陣列 onResolvedCallbacks 一個為失敗的陣列 onRejectedCallbacks
- promise 一旦成功 就不能 失敗 一旦失敗就不能成功 不能進行轉換 所以執行成功或者失敗的函式時 要判斷是不是 等待態 如果是等待態 在去執行 成功或失敗的函式 並且把其變成響應的狀態,把其值 改變,並且執行回撥函式
複製程式碼
class Promise{
constructor(exectour){
this.status="pending" //定義狀態
this.onResolvedCallbacks=[]; // 成功函式的陣列
this.onRejectedCallbacks=[]; // 失敗函式的陣列
this.value=undefined; //成功的返回值
this.season=undefined; //失敗的返回值
let resolve=(value)=>{ // 成功的回撥函式
if(this.status==='pending'){
this.status='fulfilled';
this.value=value;
this.onResolvedCallbacks.forEach(fn=>fn(this.value))
}
}
let reject=(reason)=>{ 失敗的回撥函式
if(this.status==='pending'){
this.status='rejected';
this.reason=reason;
this.onRejectedCallbacks.forEach(fn=>fn(this.reason))
}
}
exectour(resolve,reject);
}
}
module.exports=Promise;
複製程式碼
上邊程式碼的then 方法
- then 的引數有兩個,第一個引數是成功的引數 onFulfilled,第二個引數是失敗的引數 onRejected
- 執行到then 的時候 有三個狀態 成功 失敗 和等待 成功的時候執行成功的函式 失敗的時候執行失敗的函式,等待的時候就存到他們各自函式的陣列裡邊
複製程式碼
class Promise{
constructor(exectour){
//code
}
then(onFulfilled,onRejected){
if(this.status==='fulfilled'){//成功態
onFulfilled(this.value)
}
if(this.status==='rejected'){//失敗態
this.onRejected(this.reason)
}
if(this.status==='pending'){//等待態
this.onResolvedCallbacks.push(onFulfilled);
this.onRejectedCallbacks.push(onRejected);
}
}
}
module.exports=Promise;
複製程式碼
完整程式碼
class Promise{
constructor(exectour){
this.status="pending" //定義狀態
this.onResolvedCallbacks=[]; // 成功函式的陣列
this.onRejectedCallbacks=[]; // 失敗函式的陣列
this.value=undefined; //成功的返回值
this.season=undefined; //失敗的返回值
let resolve=(value)=>{ // 成功的回撥函式
if(this.status==='pending'){
this.status='fulfilled';
this.value=value;
this.onResolvedCallbacks.forEach(fn=>fn(this.value))
}
}
let reject=(reason)=>{ 失敗的回撥函式
if(this.status==='pending'){
this.status='rejected';
this.reason=reason;
this.onRejectedCallbacks.forEach(fn=>fn(this.reason))
}
}
exectour(resolve,reject);
}
then (onFulfilled,onRejected){
if(this.status==='fulfilled'){//成功態
onFulfilled(this.value)
}
if(this.status==='fulfilled'){//失敗態
this.onRejected(this.reason)
}
if(this.status==='pending'){//等待態
this.onResolvedCallbacks.push(onFulfilled);
this.onRejectedCallbacks.push(onRejected);
}
}
}
module.exports=Promise;
複製程式碼
使用 自己寫的promise
const Promise= require('./Promise');
function fn1(resolve,reject){
setTimeout(()=>{
console.log(1)
resolve(1);
})
}
new Promise(fn1).then((data)=>{
console.log('data:'+data); // data : 1
},reason=>{
console.log('raeson'+reson)
})
複製程式碼
總結 這就簡單實現了一個漏洞百出的promise ,後邊將繼續完善我們promise ,上邊的promise如果回撥的時候 丟擲一個異常那麼我們現在實現的promise 是不會做出反應的所以要考慮一下這種情況
class Promise{
constructor(exectour){
//code
try{
exectour(resolve,reject);
}catch(e){
reject(e);
}
}
}
複製程式碼
我們目前完成的promise 是不能鏈式的 所以下一步就是實現鏈式,要想實現鏈式 那麼 回撥函式返回的就是一個promise 才會現實鏈式
根據 promise a+的規範 返回一個名字叫 promise2 的一個promise
x 是回撥函式的返回值,要看看 是不是promise 如果是 取他的結果,作為promise2 成功的結果
如果返回的是一個普通值, 作為promise2 成功的結果
然後我們用 resilvePromise 解析 x 和promise2 之間的關係
複製程式碼
class Promise{
constructor(exectour){
//code
}
then(onFulfilled,onRejected){
let promise2
if(this.status==='fulfilled'){//成功態
promise2=new Promise((resolve,reject)=>{
let x= onFulfilled(this.value);
resolvePromise(promise2,x,resolve,reject)
})
}
if(this.status==='fulfilled'){//失敗態
promise2=new Promise((resolve,reject)=>{
let x= this.onRejected(this.reason)
resolvePromise(promise2,x,resolve,reject)
})
}
if(this.status==='pending'){//等待態
promise2=new Promise((resolve,reject)=>{
this.onResolvedCallbacks.push(()=>{
let x=onFulfilled(this.value)
resolvePromise(promise2,x,resolve,reject)
});
this.onRejectedCallbacks.push(()=>{
let x= this.onRejected(this.reason)
resolvePromise(promise2,x,resolve,reject)
});
})
}
return promise2 // 呼叫then後返回一個新的promise
}
}
複製程式碼
那麼我們接下來實現 resolvePromise解析 x 和promise2 之間的關係
function resolvePromise(promise2,x,resolve,reject){
// 首先判斷promise2 和x 是不是同一個promise 如果是報錯
if(promise2===x){
reject(new TypeError('迴圈引用'))
}
//如果x不是null 並且 是物件或者函式 我們進進一步去做處理 否則我們 認為他是一個值 直接傳成功就可以了
if(x!==null && (typeof x === 'object' || typeof x ==='function')){
//
let called //防止成功或失敗再去呼叫
try{ //防止取的then 出現異常
let then=x.then
if(typeof then=='function'){//如果then 是一個函式我們就認為他是一個promise
then.call(x,y=>{ // call 第一個引數是this ,後面的是成功的回撥和失敗的回撥
//y 是promise就繼續遞迴解析
if(called) return false;
called= true;
resolvePromise(promise2,y,resolve,reject);
},r=>{
if(called) return false;
called= true;
reject(r)
})
}else{
resolve(x) //then shi 一個普通物件 就直接成功
}
}catch(e){
if (called) return;
called = true;
reject(e);
}
}else{
resolve(x);
}
}
複製程式碼
那麼 我們基本上就完成了一個promise 不過promise 的幾個方法還沒有實現 那麼我們繼續完成promise上的另幾個方法
class Promise {
//code
catch(onRejected) {
// catch就是then的沒有成功的簡寫
return this.then(null, onRejected);
}
}
Promise.resolve = function (val) {
return new Promise((resolve, reject) => resolve(val))
}
Promise.reject = function (val) {
return new Promise((resolve, reject) => reject(val));
}
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(resolve, reject);
}
});
}
Promise.all = function (promises) {
return new Promise((resolve,reject)=>{
let arr = [];
let i = 0; // i的目的是為了保證獲取全部成功,來設定的索引
function processData(index,data) {
arr[index] = data;
i++;
if (i === promises.length){
resolve(arr);
}
}
for(let i = 0;i<promises.length;i++){
promises[i].then(data=>{
processData(i,data);
}, reject);
}
})
}
Promise.deferred = Promise.defer = function () {
let dfd = {};
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
})
return dfd;
}
複製程式碼
這就基本完成了一個promise 程式碼和語言的歸納還比較稚嫩,希望大家多多指點。