Promise基本使用与原理

1.异步请求

在学习promise的时候我们先看一个异步请求

javascript 复制代码
function requestData(name) {
  setTimeout(() => {
    if (name === 'test') {
      return 111;
    } else {
      return 222;
    }
  }, 1000);
}

console.log(requestData('test'));//undefined

因为setTimeout 函数是异步的,这意味着它不会立即返回结果。而是在1s后执行。在调用requestData方法时,实际打印的是requestData函数的返回值,由于此函数并没有return语句,所以返回是undefined。如果要拿到异步请求的返回值,我们要使用回调函数,使用回调函数能够拿到异步请求的返回值,是因为回调函数被设计为在异步操作完成时被调用,并将异步操作的结果作为参数。

scss 复制代码
function requestData(name, success, failed) {
  setTimeout(() => {
    if (name === 'test') {
      success(111);
    } else {
      failed(222);
    }
  }, 1000);
}

requestData(
    'test',
    (res) => console.log(res),
    (err) => console.log(err)
  )

//111

可以看到通过回调函数我们可以拿到异步函数的请求结果。但是我们需要自己去设计回调函数,而且不同的人,他设计的函数各有不同,我们还需要去了解这个函数的设计模式。因此有了promise去统一这种请求方式,另外promise还可以避免回调地狱的产生,使用then,catch方法,增大了代码的可读性。

在通过new创建Promise对象时,我们需要传入一个回调函数,我们称之为executor,这个回调函数会被立即执行,并且给传入另外两个回调函数resolve、reject,当我们调用resolve回调函数时,会执行Promise对象的then方法传入的回调函数;

2.Promise代码结构

javascript 复制代码
const promise = new Promise((resolve, reject) => {
  resolve('哈哈');
  reject('错误信息');
});

promise
  .then((res) => {
    console.log('res', res);
  })
  .catch((err) => {
    consloe.log('err', err);
  });

//res,哈哈

在这里通过executor我们调用了resolve和reject方法,但是终端打印的结果只有一个res的,即在Promise中只调用了resolve函数,这个是何Promise里面的状态有关,Promise里面有三种状态(Pending,Fulfilled,Rejected)。在上面的代码在new Promise里就是pending状态,由于先调用了resolve方法,此时状态就会变成Fulfilled。而下面的reject方法,由于此时状态不再是pending状态,将不再执行reject方法。

3.Promise的对象方法

1) then方法

then方法本身也是有返回值的, 它的返回值是Promise。如果我们返回的是一个普通值(数值/字符串/普通对象/undefined), 那么这个普通的值被作为一个新的Promise的resolve值

javascript 复制代码
promise.then(res => {
  return "aaaaaa"
}).then(res => {
  console.log("res:", res)
  return "bbbbbb"
})

//res: aaaaaa

如果我们返回的是一个Promise

javascript 复制代码
promise
  .then((res) => {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(111111);
      }, 3000);
  });
})
.then((res) => {
  console.log('res:', res);
});

//res: 11111
2)catch方法
javascript 复制代码
const promise = new Promise((resolve, reject) => {
reject('111111');
});

promise
  .then((res) => {
    console.log('res:', res);
  })
  .catch((err) => {
    console.log('err:', err);
    return 'catch return value';
  })
  .then((res) => {
    console.log('res result:', res);
  })
  .catch((err) => {
    console.log('err result:', err);
});

// err: 111111
// res result: catch return value

当调用了reject方法时会去调用catch方法,调用了catch方法后,因为返回了的是一个新的Promise对象,所以他的执行一个新的resolve,除非在调用的时候继续promise的reject,或者抛出异常,它才会调用catch方法。

  1. finally方法
javascript 复制代码
const promise = new Promise((resolve, reject) => {
  // resolve("resolve message")
  reject("reject message")
})

promise.then(res => {
  console.log("res:", res)
}).catch(err => {
  console.log("err:", err)
}).finally(() => {
  console.log("finally code execute")
})

//err: reject message
//finally code execute

这个finally方法是最终的意思,最后都会调用一下。

4.Promise类方法

1)all与allSettled
javascript 复制代码
// 创建多个Promise
const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(11111)
  }, 1000);
})

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(22222)
  }, 2000);
})

const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(33333)
  }, 3000);
})
// all
//Promise.all([p2, p1, p3, "aaaa"]).then(res => {
//  console.log(res)
//}).catch(err => {
//  console.log("err:", err)
//})
// err: 22222

// allSettled
Promise.allSettled([p1, p2, p3])
  .then((res) => {
    console.log(res);
  })
  .catch((err) => {
    console.log(err);
  });

[
  { status: 'fulfilled', value: 11111 },
  { status: 'rejected', reason: 22222 },
  { status: 'fulfilled', value: 33333 }
]

要所有的Promise都变成fulfilled时, 再拿到结果。在拿到所有结果之前, 有一个promise变成了rejected, 那么整个promise是rejected。allSettled会打印所有状态与结果

2)race与any
javascript 复制代码
// 创建多个Promise
const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(11111)
  }, 3000);
})

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(22222)
  }, 500);
})

const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(33333)
  }, 1000);
})

// race: 竞技/竞赛
// Promise.race([p1, p2, p3]).then(res => {
//   console.log("res:", res)
// }).catch(err => {
//   console.log("err:", err)
// })
//err: 22222

// any方法
Promise.any([p1, p2, p3]).then(res => {
  console.log("res:", res)
}).catch(err => {
  console.log("err:", err.errors)
})

res: 33333

race它会选择最先完成(无论成功还是失败)的那个Promise。any是根据状态执行的,只要一组中其中一个的状态变为fulfilled,那么Promise.any的状态就会变成fulfilled。

相关推荐
崔庆才丨静觅2 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60612 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了2 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅3 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅3 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅3 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment3 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅4 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊4 小时前
jwt介绍
前端
爱敲代码的小鱼4 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax