2021-03-13【技术】关于Promise中的resolve,reject,catch的理解

先来说一下Promise的三种状态

pending - 进行中
fulfilled - 成功
rejected - 失败

Promise对象,可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。
但Promise对象的状态不受外界影响,Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败),只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态,这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。

状态的改变(或者说决议)不可逆,一旦决议就不能再更改。
任何时候都可以得到这个结果,Promise对象的状态改变,只有两种可能:从pending变为fulfilled 或者 从pending变为rejected,只要这两种情况中的一种发生,其状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。
如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。
这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。


进阶开始,让我们手写一个promise
概念: promise接受一个函数 有三种 状态 俩个回调
写一个构造函数接收一个参数 有三种状态 成功结果 失败结果 成功回调 失败 回调
构造函数的原型有一个.then 方法 接收俩个参数 判断状态 如果成功调用 成功函数 失败 调用失败函数 pending 就存起来。
代码如下:

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

// promise接受一个函数 有三种 状态 俩个回调
// 写一个构造函数接收一个参数  有三种状态,此外还有:成功结果 失败结果 成功回调 失败回调
// 构造函数的原型有一个.then 方法 接收俩个参数  判断状态 如果成功调用 成功函数 ;失败 调用失败函数 pending 就存起来

function Promise (executor) {
  var _this = this
  this.state = PENDING  // 状态
  this.value = undefined  // 成功结果
  this.reason = undefined;  // 失败原因
  this.onFulfilled = [];//成功的回调
  this.onRejected = []; //失败的回调

  function resolve (value) {
    if (_this.state === PENDING) {
      _this.state = FULFILLED
      _this.value = value
      _this.onFulfilled.forEach(fn => fn(value))
    }
  }
  function reject (reason) {
    if (_this.state === PENDING) {
      _this.state = REJECTED
      _this.reason = reason
      _this.onRejected.forEach(fn => fn(reason))
    }
  }
  try {
    executor(resolve, reject)
  } catch (e) {}
}

Promise.prototype.then = function (onFulfilled, onRejected) {
  if (this.state === FULFILLED) {
    typeof onFulfilled === 'function' && onFulfilled(_this.value)
  }
  if (this.state === REJECTED) {
    typeof onRejected === 'function' && onRejected(_this.reason)
  }
  if(this.state === PENDING){
    typeof onFulfilled === 'function' && this.onFulfilled.push(onFulfilled)
    typeof onRejected === 'function' && this.onRejected.push(onRejected)
  } 
}

// module.exports = Promise;


var p = new Promise((resolve, reject)=>{
  setTimeout(()=>{
      resolve(4)
  }, 0)
})
p.then((res)=>{
  //4 res
  console.log(res, 'res')
})
p.then((res1)=>{
  //4 res1
  console.log(res1, 'res1')
})

一、对于resolve,reject简单理解

我们先构建一个Promise

//构建Promise
var promise = new Promise(function (resolve, reject) {
    if (/* 异步操作成功 */) {
        resolve(data);
    } else {
        /* 异步操作失败 */
        reject(error);
    }
});

这种方式类似构建对象,使用new来构建一个Promise。
Promise接受一个「函数」作为参数,该函数的两个参数分别是resolve和reject。这两个函数就是就是「回调函数」,由JavaScript引擎提供。

Promise实例生成以后,可以用then方法指定resolved状态和reject状态的回调函数。

//promise.then(onFulfilled, onRejected);
promise.then(function(data) {
  // do something when success
}, function(error) {
  // do something when failure
});

then方法会返回一个Promise。它有两个参数,分别为Promise从pending 变为 fulfilled和rejected时的回调函数(第二个参数非必选)。这两个函数都接受Promise对象传出的值作为参数。

.catch()

该方法是.then(undefined, onRejected)的别名,用于指定发生错误时的回调函数。

promise.then(function(data) {
    console.log('success');
}).catch(function(error) {
    console.log('error', error);
});

/*******等同于*******/
promise.then(function(data) {
    console.log('success');
}).then(undefined, function(error) {
    console.log('error', error);
});

promise对象的错误,会一直向后传递,直到被捕获。即错误总会被下一个catch所捕获。then方法指定的回调函数,若抛出错误,也会被下一个catch捕获。catch中也能抛错,则需要后面的catch来捕获。

sendRequest('test.html').then(function(data1) {
    //do something
}).then(function (data2) {
    //do something
}).catch(function (error) {
    //处理前面三个Promise产生的错误
});

此处要注意,promise一旦resolve(即成功状态)了再抛错,也不会变为rejected(失败状态),也就不会被catch了,代码如下:

var promise = new Promise(function(resolve, reject) {
  resolve();
  throw 'error';
});

promise.catch(function(e) {
   console.log(e);      //This is never called-永远不会被触发
});

如果没有使用catch方法指定处理错误的回调函数,Promise对象抛出的错误不会传递到外层代码,即不会有任何反应

关于promise中reject和catch的问题
一、reject后的东西,一定会进入then中的第二个回调,如果then中没有写第二个回调,则进入catch

var p1=new Promise((resolve,rej) => {
    console.log('没有resolve')
    //throw new Error('手动返回错误')
    rej('失败了')
 })
 p1.then(data =>{
    console.log('data::',data);
 },err=> {
    console.log('err::',err)
 }).catch(
    res => {
    console.log('catch data::', res)
 })

结果为:

没有resolve
err:: 失败了

then中没有第二个回调的情况

var p1=new Promise((resolve,rej) => {
    console.log('没有resolve')
    //throw new Error('手动返回错误')
    rej('失败了')

 })
 p1.then(data =>{
    console.log('data::',data);
 }).catch(
    res => {
    console.log('catch data::', res)
 })

结果为:

没有resolve
catch data:: 失败了

二、resolve的东西,一定会进入then的第一个回调,肯定不会进入catch

var p1=new Promise((resolve,rej) => {
    console.log('resolve')
    //throw new Error('手动返回错误')
    resolve('成功了')

 })

 p1.then(data =>{
    console.log('data::',data);
 }).catch(
    res => {
    console.log('catch data::', res)
 })

结果为:

resolve
data:: 成功了

不会进入catch的情况,只要resolve(即成功)了,就算抛出err,也不会进入catch

 var p1=new Promise((resolve,rej) => {
    console.log('resolve')
    //throw new Error('手动返回错误')
    resolve('成功了')
 })

 p1.catch(
    res => {
    console.log('catch data::', res)
 })

结果:

resolve //即成功以后永远不会进入catch

throw new Error 的情况和rej一样,但是他俩只会有一个发生
另外,网络异常(比如断网),会直接进入catch而不会进入then的第二个回调

你可能感兴趣的:(2021-03-13【技术】关于Promise中的resolve,reject,catch的理解)