ES6 中的 Promise

1、什么是Promise

  • Promise 是一个类
  • 当通过 new Promise() 创建时,需传入一个执行函数 ,我们称之为 executer
    • executer 在 Promise 创建时会立即执行,并传入两个回调函数作为参数:executer(resolve, reject)
    • 当调用 resolve 回调函数时,会执行 Promise 对象的 then 方法传入的回调
    • 当调用 reject 回调函数时,会执行 Promise 对象的 catch 方法传入的回调
  • Promise 是一个状态机,分为 3种状态
    • pending :待定状态,执行 executer 后,处于该状态。(初始状态)
    • fuifilled :兑现状态,调用 resolve 后,Promise 状态变更为 fulfilled,且无法再次更改。
    • rejected :拒绝状态,调用 reject 后,Promise 状态变更为 rejected,且无法再次更改。
javascript 复制代码
// 模拟网络请求
function request(cb) {
    let flag = !!(Math.random() <= 0.5)
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (flag) {
                resolve("成功消息")
                return;
            } 
            reject("失败消息")
        }, 1000)
    })
}

console.log("请求开始")

request().then(
    msg => {
        console.log("成功",msg)
    },
    err => {
        console.log("失败",err)
    }
)

2、resolve 的参数

  • 如果传入的是普通的值或者推向,则会传递到 then 方法的参数中
  • 如果传入的是一个 Promise ,则当前 Promise 状态会由传入的Promise决定
javascript 复制代码
const prom = new Promise((resolve, reject) => {
    resolve('success')
})

new Promise((resolve, reject) => {
    resolve(prom)
}).then(data => {
    console.log("data", data)
}).catch(err => {
    console.err("err", err)
})

// 输出 data success
  • 如果传入的是一个 thenable对象 ,会执行对象的 then 方法,由该 then 方法决定后续状态
javascript 复制代码
new Promise((resolve, reject) => {
    resolve({
        then(resolve,reject) {
            reject("error)
        }
    })
}).then(data => {
    console.log("res", res)
}).catch(err => {
    console.log("err", err)
})

// 输出 err error

3、Promise 的实例方法

then 方法

  • 概念

    • 通过 then 方法可以对 Promise 中的 resolve 进行处理,then 方法的返回值是一个新的 Promise 实例
  • 多次调用 then 方法

    • 同一个 Promise 实例可以同时调用多个 then 方法,当 Promise 中的 resolve 被调用时,所有的 then 方法传入的回调函数都会被调用

      javascript 复制代码
      const prom = new. Promise(resolve => {
          resolve("你好")
      })
      
      prom.then(msg => console.log(msg))
      prom.then(msg => console.log(msg))
      prom.then(msg => console.log(msg))
      
      /* 输出
      你好
      你好
      你好
      */
  • then 方法传入的回调函数可以有返回值

    • 如果返回的是普通值 ,那么这个普通值作为一个新的 Promise 的 resolve 值

      javascript 复制代码
      const prom = new Promise(resolve => {
          resolve("你好");
      })
      
      prom.then(() => 'then').then(res => console.log(res))
      
      // prom.then(() => 'then')等价于
      prom.then(() => {
          return new Promise(resolve => {
              resolve('then')
          })
      })
      
      // 输出 then
    • 如果返回的是 Promise ,那么就可以再次调用此 Promise 的 then 方法

    • 如果返回的是一个 thenable 对象 ,则 resolve 会传递给下一个 Promise

      javascript 复制代码
      const promise = new Promise(resolve => {
        resolve('你好')
      })
      
      promise.then(() => {
        return {
          then(resolve) {
            return resolve('success')
          }
        }
      }).then(msg => console.log(msg))
      
      // 输出 success

catch 方法

除了 then 方法的第二个参数来捕获 reject 错误外,我们还可以通过 catch 方法来捕获,catch 返回的也是一个新的 Promise

javascript 复制代码
const promise = new Promise((resolve, reject) => {
  reject('error') 
})

promise.then(undefined, err => {
  // 打印err
  console.log(err)
})
// 这种写法不太符合'promise/a+规范'
promise.catch(err => {
  // 打印err
  console.log(err)
})
// 符合规范的写法
promise.then(() => {}).catch(err => {console.log(err)})

*注意* catch 本质上是对 Promise 的 then 方法的封装,所以同样也是可以多次调用 的,只要保证 Promise 实例的状态是 rejected ,那么就会调用 catch 方法

finally 方法

Promise 实例 状态无论是变更为 fulfilled 还是 rejected,finally 方法都会执行,finally 方法不接受任何的参数

javascript 复制代码
const promise = new Promise((resolve, reject) => {
  reject('error') 
})

promise.then(() => {}).catch(err => {console.log(err)}).finally(() => {
  console.log('finally code execute')
})

4、Promise 的类方法

resolve 方法

  • 参数
    • 参数本身是 Promise
    • 参数是 原始值/普通对象
    • 参数是一个 thenable对象
javascript 复制代码
const foo = {
    name: "alex"
}

function bar(obj) {
    return new Promise(resolve => {
        resolve(obj)
    })
}

bar(foo).then(res => {
    console.log(res)
})

// 其中的 function bar 等价于

function bar1(obj) {
    return Promise.resolve(obj)
}

reject 方法

Promise.reject() 方法和 Promise.resolve() 方法 用法类似,主要区别是,reject方法用于处理Promise 拒绝逻辑

all 方法

Promise.all(proms) ,参数接收一个 Promise 队列,返回的是一个 Promise 实例,当 proms 总的所有 Promise 执行完成状态均为 fulfilled 时,结果实例的状态才会变为 fulfilled,反之,结果实例的状态为 rejected。

当 Promise.all(proms) 的状态为 fulfilled 时,then(res) 的参数 res 就是 proms 对应实例成功后的值所形成的数组。

javascript 复制代码
let i = 0;
function genPromise() {
    return Promise.resolve(`success${i = i + 1}`)
}

const proms = [
    genPromise(),
    genPromise(),
    genPromise(),
];

Promise.all(proms).then(res => {
    console.log('res' , res)
})

// 输出 ['success1', 'success2', 'success3']

当 Promise.all(proms) 的参数 proms 中存在 rejected 时,结果实例状态也会更改为 rejoiced,同时返回停止运行剩余 Promise ,结果返回 状态为 rejected 的 Promise 的值。

javascript 复制代码
let i = 0;
function genPromise() {
  return new Promise(resolve => {
    resolve(`success${(i = i + 1)}`)
  })
}
const promiseArr = [
  genPromise(),
  new Promise((resolve, reject) => {
    reject('error1')
  }),
   new Promise((resolve, reject) => {
    reject('error2')
  })
]
Promise.all(promiseArr).then(res => {
  console.log('res', res)
}).catch(err => {
  console.log(err)
})

// 输出 'error1'

allSettled 方法

  • 参数接收一个 Promise 队列,返回 一个Promise 实例
  • 返回 Promise 实例,会在所有 Promise 实例执行完毕后,状态方可变更为 fulfilled,且结果实例状态只能由 pending ------> fulfilled.
  • 无论队列中的 Promise 实例的状态如何,都能获取到结果
javascript 复制代码
const promiseArr = [
  new Promise((resolve, reject) => {
    resolve('success1')
  }),
  new Promise((resolve, reject) => {
    reject('error')
  }),
  new Promise((resolve, reject) => {
    resolve('success2')
  }),
]

Promise.allSettled(promiseArr).then(res => {
  console.log('res', res)
})

/* 结果:
    res [
      { status: 'fulfilled', value: 'success1' },
      { status: 'rejected', reason: 'error' },
      { status: 'fulfilled', value: 'success2' }
    ]
*/

race 方法

  • 参数接收一个 Promise 队列,返回一个 Promise 实例
  • Promise 队列的完成情况进行监控,当某个任务最前完成(无论是fulfilled/rejected),那么返回的结果实例状态也会对应的变更,同时捕获最先完成的 Promise 的结果
javascript 复制代码
const promiseArr = [
   new Promise((resolve, reject) => {
    setTimeout(() => {
       resolve('success1')
    }, 1000)
  }),
  new Promise((resolve, reject) => {
    setTimeout(() => {
          reject('error')
    }, 2000)
  }),
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('success2')
    }, 3000)
  }),
]

Promise.race(promiseArr).then(res => {
  console.log('res', res)
}).catch(err => {
  console.log('err', err)
})

// 结果 res success1

any 方法

  • 参数接收一个 Promise 队列,返回一个 Promise 结果实例
  • 当某个 Promise 状态变更为 fulfilled 或 所有的 Promise 状态均为 rejected 时,结果实例的状态才能确定并返回
javascript 复制代码
const promiseArr = [
   new Promise((resolve, reject) => {
    setTimeout(() => {
       reject('error')
    }, 2200)
  }),
  new Promise((resolve, reject) => {
    setTimeout(() => {
          reject('error')
    }, 2000)
  }),
  new Promise((resolve, reject) => {
    setTimeout(() => {
      reject('error')
    }, 3000)
  }),
]

Promise.any(promiseArr).then(res => {
  console.log('res', res)
}).catch(err => {
  console.log('err', err)
})
// 遇到第一个fullfilled,那么转变返回的Promise实例的状态
// 如果所有的都是rejected, 那么只有所有执行完毕后,返回的Promise实例才会转变
// 并且会抛出错误
相关推荐
光影少年2 小时前
React和Vue的区别?
前端·vue.js·react.js
遗憾随她而去.2 小时前
前端跨页面通信:8 种方案全解析(附实战案例)
前端
何中应2 小时前
<el-tag>标签使用
前端·vue.js·elementui
清汤饺子2 小时前
Cursor 独有的 12 个技巧:这些是 Claude Code 没有的
前端·后端·ai编程
白菜__2 小时前
阿里V2滑块小程序版本
javascript·爬虫·网络协议·小程序·node.js
Mr数据杨2 小时前
【Dv3Admin】FastCRUD富文本编辑器操作
前端·javascript
倾颜2 小时前
零成本本地大模型!用 Next.js + Ollama + Qwen3 打造流式聊天应用
前端·后端·ai编程
英俊潇洒美少年2 小时前
react useDeferredValue和useTransition有啥区别
javascript·react.js·ecmascript