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。

相关推荐
卡兰芙的微笑23 分钟前
get_property --Cmakelist之中
前端·数据库·编辑器
覆水难收呀26 分钟前
三、(JS)JS中常见的表单事件
开发语言·前端·javascript
猿来如此呀33 分钟前
运行npm install 时,卡在sill idealTree buildDeps没有反应
前端·npm·node.js
hw_happy39 分钟前
解决 npm ERR! node-sass 和 gyp ERR! node-gyp 报错问题
前端·npm·sass
FHKHH43 分钟前
计算机网络第二章:作业 1: Web 服务器
服务器·前端·计算机网络
视觉小鸟1 小时前
【JVM安装MinIO】
前端·jvm·chrome
二川bro2 小时前
【已解决】Uncaught RangeError: Maximum depth reached
前端
qq22951165023 小时前
python毕业设计基于django+vue医院社区医疗挂号预约综合管理系统7918h-pycharm-flask
前端·vue.js·express
八了个戒3 小时前
Koa (下一代web框架) 【Node.js进阶】
前端·node.js
Sca_杰3 小时前
vue2使用npm引入依赖(例如axios),报错Module parse failed: Unexpected token解决方案
前端·javascript·vue