前端学习笔记--Promise

217 阅读4分钟

Promise是什么

Promise对象用于异步操作,它表示尚未完成且预计在未来完成的异步操作。

可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果

Promise构造函数

const p=new Promise((resolve,reject)=>{
    if(成功){
        resolve('success')
    }else{
        reject('error')
    }
})

构造函数传入一个函数,这个函数的两个参数(resolve,reject)是函数类型,由构造函数内部提供。


Promise实例有三种状态:pending、fulfilled 、rejected,状态只能由 Pending 变为 Fulfilled 或由 Pending 变为 Rejected ,且状态改变之后不会在发生变化,会一直保持这个状态

resolve和reject

  • resolve函数:将当前Promise实例的状态由pending转为fulfilled(this.status=fulfilled)
  • reject函数:将当前Promise实例的状态由pending转为rejected(this.status=rejected)

resolve函数传入的值

  • 如果传入的值不属于Promise实例,则该值会作为成功的回调函数的参数(在then方法的参数指定了回调函数)
  • 如果传入的是Promise实例p1,则当前Promise实例p2的状态由p1决定,则p2的回调函数会等待p1的状态改变才执行。
const p1 = new Promise(function (resolve, reject) {
  // ...
});

const p2 = new Promise(function (resolve, reject) {
  // ...
  resolve(p1);
})

Promise的值

new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('FULFILLED')
  }, 1000)
})

这里resolve 传入的 "FULFILLED" 就是 Promise 的值

resolve 和 reject 都可以传入任意类型的值作为实参,表示 Promise 对象成功(Fulfilled)和失败(Rejected)的值

then函数

const p=new Promise((resolve,reject)=>{
    if(成功){
        resolve('success')
    }else{
        reject('error')
    }
})
p.then(function(val){
    console.log(val);   //success
},function(err){
    console.log(err);   //error
})

参数可选

promise.then(onFulfilled, onRejected)

  • 如果参数不是函数,则被忽略,会发生值穿透
Promise.resolve(1)
  .then(2)
  .then(Promise.resolve(3)) //Promise.resolve(3)不是函数
  .then(console.log)//console.log是一个函数。这个可以接收,所以结果是console.log(1).

运行结果:

1
  • then函数的参数是两个回调函数,then函数内部通过this(当前Promise实例p)的状态status来决定调用哪一个回调。
    • onFulfilled:其第一个参数为promise 成功状态传入的值( resolve 执行时传入的值,值保存在Promise实例上,因此可以访问)
  • onRejected:其第一个参数为 promise 失败状态传入的值( reject 执行时传入的值)

返回值

  • then函数返回的是一个新的Promise实例,所以then可以链式调用。

then函数可以多次调用

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log('once')
    resolve('success')
  }, 1000)
})

const start = Date.now()
promise.then((res) => {
  console.log(res, Date.now() - start)
})
promise.then((res) => {
  console.log(res, Date.now() - start)
})

运行结果:

once
success 1005
success 1007

then函数返回的Promise实例的状态

返回的新的Promise实例的状态依赖于当前then方法的回调函数执行的情况及返回值

  • 如果回调返回的是一个值,则将该值作为Promise实例的值,传入下一个then的回调函数的参数
let promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve()
  }, 1000)
})
promise2 = promise1.then(res => {
  // 返回一个普通值
  return '这里返回一个普通值'
})
promise2.then(res => {
  console.log(res) //1秒后打印出:这里返回一个普通值
})

  • 如果回调函数执行过程出错,则Promise实例的状态为rejected
let promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('success')
  }, 1000)
})
promise2 = promise1.then(res => {
  throw new Error('这里抛出一个异常e')
})
promise2.then(res => {
  console.log(res)
}, err => {
  console.log(err) //1秒后打印出:这里抛出一个异常e
})
  • 如果回调函数返回了一个新的Promise实例p2,则当前Promise实例的状态由p2的状态决定,等到p2状态改变才会执行后续的回调。
let promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve()
  }, 1000)
})
promise2 = promise1.then(res => {
  // 返回一个Promise对象
  return new Promise((resolve, reject) => {
    setTimeout(() => {
     resolve('这里返回一个Promise')
    }, 2000)
  })
})
promise2.then(res => {
  console.log(res) //3秒后打印出:这里返回一个Promise
})
  • 如果返回的是一个Error对象
Promise.resolve()
  .then(() => {
    return new Error('error!!!')
  })
  .then((res) => {
    console.log('then: ', res)
  })
  .catch((err) => {
    console.log('catch: ', err)
  })

运行结果:

then: Error: error!!!
    at Promise.resolve.then (...)
    at ...

解释:.then或.catch的参数--回调函数返回一个error对象并不会抛出错误,不会后续的.catch捕获到,如果改为throw new Error('error!!!')则会被catch捕获到。

Promise.resolve()

  • 参数:普通值 / Promise对象 / thenable对象(即带有"then" 方法)
  • 返回值:
    • 当参数是一个普通值,返回一个resolved类型的Promise对象
    • 当是Promise对象,则返回这个Promise对象
    • 当是thenable对象,则返回的Promise对象会“跟随”这个thenable的对象,采用它的最终状态;
var p1 = Promise.resolve( 1 );
var p2 = Promise.resolve( p1 );
var p3 = new Promise(function(resolve, reject){
  resolve(1);
});
var p4 = new Promise(function(resolve, reject){
  resolve(p1);
});

console.log(p1 === p2); 
console.log(p1 === p3);
console.log(p1 === p4);
console.log(p3 === p4);

p4.then(function(value){
  console.log('p4=' + value);
});

p2.then(function(value){
  console.log('p2=' + value);
})

p1.then(function(value){
  console.log('p1=' + value);
})

作者:艾特老干部
链接:https://juejin.cn/post/6844903488695042062
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

输出:

true
false
false
false
p2=1
p1=1
p4=1

解析:

为什么p2的then比p1的先执行呢?因为p2的then写在前
为什么p4的then最后调用呢?因为resolve函数接收的是一个Promise对象,resolve会对该对象拆箱,获取p1的状态和值,是一个异步操作。

函数解析

自己实现Promise

资料

十道练习题

必会