玄学Promise把我整神了!还好我这个重庆人本身就很神:)

发布于:2024-05-10 ⋅ 阅读:(20) ⋅ 点赞:(0)

理解好Promise的输入输出是理解Promise的关键所在。本文将一步步的细究Promise每一个实列方法与静态方法的输入输出,并在最后将出示几道大厂面试题用于学习后的验证。

注意:想要深入理解Promise的运行原理,必须要了解最基本的事件循环机制。二者是相辅相成,你只有我,我中有你的存在。 为防止完全不懂事件循环机制,纯粹好奇Promise的同学阅读本文,我对事件循环机制作出如下总结: 事件循环中分为了主线程,宏任务队列和微任务队列。微任务内部函数执行顺序优先度远大于宏任务

  1. V8引擎首先开始执行主线程
  • 遇到如console.log()这种同步代码就直接执行
  • 遇到属于微任务的方法,将方法内部的回调函数加入到微任务队列中;
  • 遇到属于宏任务的方法,将方法内部的回调函数加入到宏任务队列中。
  1. 然后主线程将所有同步代码执行完毕之后,执行微任务宏任务中的回调函数
  • 系统会查看微任务队列中是否存在微任务,如果存在,则将所有微任务按照先后顺序(先进先出)放入主线程全部进行执行,然后执行完成清空微任务。
  • 微任务完成后,会查看宏任务队列中是否存在宏任务,如果存在,则将所有宏任务按照先后顺序(先进先出)放入主线程全部进行执行,然后执行完成清空宏任务。
  1. 最后完成所有代码的执行,此为事件循环

什么是Promise?

要理解Promise,我们需要理解他的历史由来。换句话说就是,他为什么出现,解决了什么痛点,有什么缺陷。 一言以蔽之:解决回调地狱问题的一种异步编程的解决方案

创建一个Promise对象

new Promise((resolve, reject) => {
        resolve() 或者 reject()
    })

new Promise(cellback)

实列化一个promise对象,该代码传入一个回调函数。并且该回调函数代码内部执行逻辑为同步代码(什么是同步代码请看上文)

我们来看看实例化一个promise对象时,内部回调函数做的事情

new Promise((resolve, reject) => {
  console.log(1);
  resolve();
  console.log(2);
})
new Promise((resolve, reject) => {
  console.log(3);
  reject();
  console.log(4);
})

答案

1
2
3
4
Uncaught (in promise) undefined
// ↑这是reject引发的错误,其中的undefined是执行reject函数未传参导致的

简单来说就是new一个对象的时候,内部的回调函数我们可以当作同步代码来做

使用resolve()获取Promise内部的值

let promise1 = new Promise((resolve, reject) => {
  resolve(1);
})
promise.then((res)=>{
  console.log("我是第一个",res)
})
我是第一个 1

使用reject()获取Promise内部的值

let promise2 = new Promise((resolve, reject) => {
  reject(2);
})
promise2.then((res)=>{
  console.log("我是第一个",res)
},(res)=>{
  console.log("我是第二个",res)
})

答案

我是第二个 2
Promise {<fulfilled>: undefined}

我们也能将上述代码轻松化简为如下代码

Promise.resolve(1).then((res) => {console.log("我是resolve的",res)});
Promise.reject(2).then((res) => {},(res)=>{console.log("我是reject的",res)});

实例方法:

then()

then函数是整个使用Promise对象的精髓所在,正所谓使用了then()函数才使得整个异步编程脱离了回调地狱之中,才让我们在网络请求之中获得我们需要的网络数据。 要理解then()函数首先需要理解的其实是then()函数内部的回调函数,而关键在于这个回调函数的输入与输出,在关于实例化一个promise对象时我们讲了,每一个then()函数接收的参数为实列化对象时所调用的方法。

  • 调用resolve()方法,将Promise对象的状态从“Pending”变成“fulfilled
  • 调用reject()方法,将Promise对象的状态从“Pending”变成“rejected

注意:pending状态又称之为未决状态(unsettled),fulfilled与rejected又统称为已决状态(settled) 状态一经改变,绝对不可能再发生变化

Promise.resolve().then(() => 1); // 返回值为 new Promise(resolve => resolve(1))
Promise.resolve().then(() => Promise.resolve(2)); // 返回 
Promise.resolve().then(() => {
  throw new Error('abc')
}); // 返回 new Promise(resolve => resolve(Promise.reject(new Error('abc'))))
Promise.reject().then(() => 1, () = 2); // 返回值为 new Promise(resolve => resolve(2))

现在我们来彻底理清then的返回值:

简而言之:所有then()函数内部回调函数的返回值都会包一层Promise.resolve()

Promise.resolve().then(() => {
  return 1
});
// 返回值为
new Promise(resolve =>{
  return  resolve(1)
})
Promise.resolve().then(() => {
  return Promise.resolve(2)
});
// 返回值为
new Promise(resolve => {
  return resolve(Promise.resolve(2))
})
Promise.resolve().then(() => {
  throw new Error('abc')
}); 
// 返回值为
new Promise(resolve => {
  return resolve(Promise.reject(new Error('abc')))
})
Promise.reject().then(() => 1, () = 2); 
// 返回值为 
new Promise(resolve => {
  return resolve(2)
})

.catch()

哪catch的返回值又是什么呢? 简而言之就是所有的返回值都会包一层Promise.resolve()

Promise.reject().catch(() => 3); 
// 返回值为 
new Promise(resolve => resolve(3))
Promise.resolve().catch(() => 4); 
// 返回值为 
new Promise(resolve => resolve(调用catch的promise对象))

.finally

哪catch的返回值又是什么呢? 其实道理一样的与上同理


静态方法

promise.resolve()

将现有对象转为promise对象。方法也会返回一个新的promise实例。

const p1 = Promise.resolve('p1-resolve')
p1.then((val) => {
  console.log(val)
})
Promise.resolve().then(() => {
  return Promise.resolve('123')
}).then((val) => {
  console.log(val) // 123
})

举几个例子提高我们对该方法的理解

  1. 当参数是一个 Promise 实例 如果参数是 Promise 实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。
const thenable = {
  then: function(resolve, reject) {
    resolve('abc')
  }
};
  1. 给Promise.resolve()方法传入一个带有then方法的对象,会将这个对象转为 Promise 对象,然后立即执行thenable对象的then()方法。
const thenable = {
  then: function(resolve, reject) {
    resolve('abc')
  }
}
const p1 = Promise.resolve(thenable).then((val) => {
  console.log(val)
})

Promise.reject()

Promise.reject() 方法返回一个带有拒绝原因的 Promise 对象

Promise.reject(new Error('err')).catch(e => {
  console.log(e.message) // err
})

Promise.all()

Promise.all()将多个Promise放在一个数组中,当整个数组的全部promise成功时才会返回成功,当数组中的promise有一个出现失败时就返回失败 (失败的原因是第一个失败promise的结果)。

简而言之:全部成功才是成功,一个失败全部打回

const delay = (ms, msg) => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(msg)
    }, ms)
  })
}
const p1 = delay(1500, 'p1')
const p2 = delay(2000, 'p2')
const p3 = delay(1000, 'p3')
Promise.all([p1, p2, p3]).then(value => {
  console.log(value) // 2s后打印 [ 'p1', 'p2', 'p3' ]
})

Promise.race()

该方法用于并发启动多个 Promise,并且只返回第一个完成(无论是 resolve 还是 reject)的 Promise 的结果。换句话说,Promise.race() 方法就像是多个 Promise 之间的赛跑,哪个 Promise 最先到达终点(即变为 fulfilled 或 rejected 状态),整个 race 就会立即结束,并采用该 Promise 的结果。

简而言之:谁最快成功我就要谁的结果

const delay = (ms, msg) => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(msg)
    }, ms)
  })
}
const p1 = delay(1500, 'p1')
const p2 = delay(2000, 'p2')
const p3 = delay(1000, 'p3')
Promise.race([p1, p2, p3]).then(value => {
  console.log(value) // p3
})

Promise.allSettled()

该方法返回一个新的 Promise 对象。只有等到参数数组的所有 Promise 对象都的状态都已决(不管是fulfilled还是rejected),返回的 Promise 对象的状态才会已决。

简而言之:管他成不成功,干就完了

const delay = (ms, msg, isReject = false) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      isReject ? reject(msg) : resolve(msg)
    }, ms)
  })
}
const p1 = delay(1500, 'p1')
const p2 = delay(2000, 'p2')
const p3 = delay(1000, 'p3', true)
Promise.allSettled([p1, p2, p3]).then(value => {
  console.log(value) // 2s后打印
  /**
   [
    { status: 'fulfilled', value: 'p1' },
    { status: 'fulfilled', value: 'p2' },
    { status: 'rejected', reason: 'p3' }
  ]
   */
})

Promis.any()

ES2021 引入了Promise.any()方法。该方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例返回。 只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。

Promise.any()跟Promise.race()方法很像,只有一点不同,就是Promise.any()不会因为某个 Promise 变成rejected状态而结束,必须等到所有参数 Promise 变成rejected状态才会结束。

简而言之:全部为同一个状态时就返回同一个状态

const delay = (ms, msg, isReject = false) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      isReject ? reject(msg) : resolve(msg)
    }, ms)
  })
}
const p1 = delay(1500, 'p1')
const p2 = delay(2000, 'p2')
const p3 = delay(1000, 'p3', true)
Promise.any([p1, p2, p3]).then(value => {
  console.log(value) // 2s后打印: p1
})



白哥精品:


网站公告

今日签到

点亮在社区的每一天
去签到