6.Promise進(jìn)階篇

then的用法

需求: 分段讀取,第一個(gè)的輸出是下一個(gè)的輸入
let fs = require('fs');
缺陷: 1.不好維護(hù),回調(diào)嵌套 2.異步錯(cuò)誤處理不能統(tǒng)一
fs.readFile('./name.txt','utf8',function(err,data){
  fs.readFile(data,'utf8',function(err,data){
    console.log(data);
  })
})

變成promise
function read(url) {
  return new Promise((resolve,reject)=>{
    fs.readFile(url,'utf8',function(err,data){
      if(err) reject(err)
      resolve(data);
    })
  })
}
// promise執(zhí)行,并且采用它的狀態(tài),如果成功會(huì)將成功的結(jié)果向外層的下一個(gè)then傳遞
read('./name.txt').then((data)=>{
  //return read(data)
  return read(data+1) //錯(cuò)誤
},(err)=>{
  console.log(err)
}).then((data)=>{
  console.log(data)
},(err)=>{
  console.log(err);
  return false  // 如果返回的是一個(gè)普通值 那么會(huì)將這個(gè)值作為下一次的成功的結(jié)果
}).then((data)=>{
  console.log(data)  //false
  // 希望在這里不要再繼續(xù)向下走then
  // throw now Error()  錯(cuò)誤也會(huì)走到外層錯(cuò)誤中
  return new Promise(()=>{}); // 終止promise 可以返回一個(gè)pending的promise
},(err)=>{
  console.log(err);
}).then((data)=>{
  console.log('success')
},(err)=>{
  console.log('erroe');
}) 

// 總結(jié)
// 1. 只有兩種情況會(huì)失敗 返回一個(gè)失敗的promise  或者拋出異常
// 2. 每次執(zhí)行promise的時(shí)候,都會(huì)返回一個(gè)新的promise實(shí)例

then.js

1.(then中傳遞的函數(shù))判斷成功和失敗函數(shù)的返回結(jié)果
2.判斷是不是prmise 如果是promise就采取它的狀態(tài)
3.如果不是promise 直接將結(jié)果傳遞下去

let Promise = require('./promise')
let p1 = new Promise((resolve, reject) => {
  resolve(1000);
})
let p2 = p1.then((data) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(new Promise((resolve, reject) => {
        resolve(1000)
      }))
    }, 0)
  });
  // return new Promise((resolve, reject) => {
  //   setTimeout(() => {
  //     resolve('hhh')
  //   }, 0)
  // });
  // throw new Error('錯(cuò)了')
},(err) => {
  console.log(err)
})
let p3 = p2.then((data) => {
  console.log('11', data);
  return 3
},(err) => {
  console.log(1, err)
})
p3.then((data) => {
  console.log('22', data)
},(err) => {
  console.log(2, err)
})



//問題一 x和promise2是一個(gè)的情況

// let promise = new Promise((resolve, reject) => {
//   resolve();
// })

// let promise2 = promise.then(() => {
//   return promise2;
// })
// promise2.then(null, (err) => {
//   console.log(err) //會(huì)打印 Chaining cycle detected for promise #<Promise>
// })

promise.js

const PENDING = 'PENDING' //等待態(tài)
const FULFILLED = 'FULFILLED' //成功態(tài)
const REJECTED = 'REJECTED' //失敗態(tài)
// 因?yàn)樗械膒romise,都遵循這個(gè)規(guī)范, 規(guī)定 這里這個(gè)寫法應(yīng)該兼容所有的promise
let resolvePromise = (promise2, x, resolve, reject) => {
  // 判斷x值
  // promise和x不能是一個(gè)(自己等著自己去在做事),如果是一個(gè)就直接拋錯(cuò)
  if(promise2 === x) {
    return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
  }
  if(typeof x === 'object' && x !== null || typeof x === 'function') {
    let called;  //  內(nèi)部測(cè)試的時(shí)候會(huì)成功和失敗都調(diào)用
    try {
     let then = x.then; // 取then  報(bào)錯(cuò)原因:有可能這個(gè)then屬性通過(guò)Object.defineProperty來(lái)定義的
     if(typeof then === 'function') { // 當(dāng)前有then方法 認(rèn)為是一個(gè)promise
      then.call(x, y => {
        if(called) {
          return
        }
        called = true; // 防止多次調(diào)用成功和失敗
        //  resolve(y); // 采取promise的成功結(jié)果將值向下傳遞
        resolvePromise(promise2, y, resolve, reject); //  y可能還是一個(gè)promise, 遞歸resolvePromise,直到解析出一個(gè)普通值為止
       }, r => {
        if(called) {
          return
        }
        called = true;
        reject(r)  // 采取失敗結(jié)果向下傳遞
       })    // 能保證不用再次取then的值
     } else {
       resolve(x) //說(shuō)明x 是一個(gè)普通的對(duì)象 直接成功即可
     }
    } catch (e) {
      // 失敗了 有可能還能調(diào)成功
      if(called) {
        return
      }
      called = true;
      reject(e)
    }
  } else {
    // x 是個(gè)普通值  直接讓promise2成功即可 
    resolve(x)
  }
}
class Promise {
  constructor(executor){
    this.state = PENDING; 默認(rèn)等待態(tài)
    this.value = undefined;
    this.reason = undefined;
    this.OnResolvedCallbacks = []; // 存放成功時(shí)的回調(diào)
    this.OnRejectedCallbacks = []; // 存放失敗時(shí)的回調(diào)
    // 只有狀態(tài)是等待態(tài)時(shí) 才可以更新狀態(tài)
    let resolve = (value) {
      if(this.status === PENDING) {
        this.status = FULFILLED
        this.value = value
        this.OnResolvedCallbacks.forEach(fn=>fn()); //發(fā)布的過(guò)程
      }
    }
      let reject = (reason) {
        if(this.status === PENDING) {
          this.status = REJECTED 
          this.reason = reason
          this.OnRejectedCallbacks.forEach(fn=>fn()); //發(fā)布的過(guò)程
      }
    }
      // executor 執(zhí)行的時(shí)候 需要傳入兩個(gè)參數(shù),給用戶改變狀態(tài)
    try {
        executor(resolve, reject)
      } catch (e) {
        reject(e) //表示當(dāng)前有異常,那就使用這個(gè)異常作為promise失敗的原因
      }
    }
  then(onFulfilled, onRejected){   // then方法就是異步的
    // 首先判斷兩個(gè)參數(shù)是否為函數(shù)類型,因?yàn)閮蓚€(gè)參數(shù)時(shí)可選參數(shù)
    onResolved = typeof onResolved === 'function'? onResolved:(data)=>data
    onRejected = typeof onRejected === 'function'? onRejected:(err)=>{
      throw err
    }
    let promise2 = new Promise((resolve,reject)=>{ // executor 會(huì)立刻執(zhí)行
      if(this.status === FULFILLED){
      // 定時(shí)器是因?yàn)閞esolvePromise能拿到promise2 
     //  try...catch..是因?yàn)楫惒酱a無(wú)法被外部try...catch..捕獲
        setTimeout(()=>{
          try {
           let x = onFulfilled(this.value)
            // x 可能是promise ,也可能是普通值
            // 判斷x的值 =》 promise2的狀態(tài)
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e)
          }
        },0)
       }
      if(this.status === REJECTED){
        setTimeout(()=>{
          try {
           let x = onRejectrd(this.reason)
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e)
          }
        },0)
      }
      //  異步情況
      if(this.status === PENDING){
          // 先訂閱
        this.OnResolvedCallbacks.push(()={
          // todo
          setTimeout(()=>{
            try {
             let x = onFulfilled(this.value)
              resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e)
            }
          },0)
        })
        this.OnRejectedCallbacks.push(()={
          setTimeout(()=>{
            try {
             let x = onRejectrd(this.reason)
              resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e)
            }
          },0)
        })
      }
    })
    return promise2;
  }
}
Promise.defer = Promise.deferred = function () {
  let dfd = {};
  dfd.Promise = new Promise((resolve, reject) => {
    dfd.resolve = resolve;
    dfd.reject = reject;
  })
  return dfd
}
module.exports = Promise

dfd.js

let Promise = require('./promise');
let fs = require('./fs');
// Promise.defer() 可以解決封裝嵌套的問題
 function read(url) {
  //  return new Promise((resolve, reject) => {
     fs.reafFile(url, 'utf8', function(err, data) {
       if(err) dfd.reject(err);
       dfd.resolve(data);
     })
     return dfd.promise
  //  })
 }
 read('./name.txt').then(data => {
   console.log(data)
 })

all.js

// Promise.all 可以實(shí)現(xiàn)等待所有的異步執(zhí)行完后 拿到統(tǒng)一結(jié)果
// 解決異步并發(fā) 同步處理結(jié)果
let Promise1 = require('./promise');
let fs = require('fs');
// Promise.defer() 可以解決封裝嵌套的問題
 function read(url) {
  //  return new Promise((resolve, reject) => {
    let dfd = Promise1.defer();
     fs.readFile(url, 'utf8', function(err, data) {
       if(err) dfd.reject(err);
       dfd.resolve(data);
     })
     return dfd.promise
  //  })
 }
 const isPromise = (value) => {
  if(typeof value === 'object' && value !== null || typeof value === 'function') {
    if( typeof value.then === 'function') {
      return true;
    }
  } else {
    return false;
  }
 }
 Promise.all = function(values) {
   return new Promise((resolve, reject) => {
     let arr = [];
     let index = 0;  // 解決多個(gè)異步并發(fā)問題 要使用計(jì)數(shù)器
     function processData(key, value) {
      arr[key] = value;
      if(++index === values.length) {
        resolve(arr)
      }
     }
     for(let i = 0; i< values.length; i++) { //let
       let current = values[i];
       if(isPromise(current)) {
         current.then((data) => {
           processData(i, data);
         },reject)
       } else {
         processData(i, current)
       }
     }
   })
 }
 // all 類方法(靜態(tài)方法)返回promise 全部成功才成功, 任何一個(gè)失敗就失敗了
 Promise.all([1, 2, 3, read('./name.txt'), 4,5]).then(data => {
   console.log(data)   //  [ 1, 2, 3, name, 4, 5 ]
 })

finally.js

// finally  最終的  try catch finally   es9// node9


let p = new Promise((resolve, reject) => {
  resolve(100);
  // reject(100)
});
Promise.prototype.finally = function(cb) {
  return  p.then(data => {
    // Promises.resolve()  可以等待promise執(zhí)行完成
    return Promise.resolve(cb().then(() => data))
    // cb();  // finally  傳入的函數(shù) 無(wú)論成功還是失敗都會(huì)執(zhí)行
    // return data // 如果是成功 會(huì)走到下一個(gè)成功里
  }, err => {
    return Promise.resolve(cb().then(() => {
      throw err;
    }))
    // cb();
    // throw err;
  }) 
}
// Promise.prototype.finally = function(cb) {
//   return p.then(
//     data => Promise.resolve(cb().then(() => data)),
//     err => Promise.resolve(cb().then(() => {
//       throw err;
//     }))
//   )
// }
p.finally(() => { // 返回的是一個(gè)promise實(shí)例
  console.log('最終的')
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve();
    }, 3000)
  })
}).then(data => {
  console.log(data)
}).catch(e => {
  console.log(e)
})

// 1) 如果放的普通值會(huì)將這個(gè)值包裝成promise, 如果放的是promise 會(huì)等待這個(gè)promise執(zhí)行完后再繼續(xù)執(zhí)行
Promise.resolve(1).then(data => {
  console.log(data)
})
// 1)用2)理解3)編寫
//Promise.reject
// Promise.race
// Promise.catch
// Promise.try
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容