js基础之Promise详解

1. 是什么

Promise是一种异步编程的解决方案,用于处理异步操作并返回结果。
主要作用是解决回调函数嵌套(回调地狱)的问题,使异步操作更加清晰、易于理解和维护。

2. 怎么用

Promise有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。当一个Promise被创建时,它的状态为pending。当异步操作完成并成功时,Promise的状态会变为fulfilled,并返回一个结果。当异步操作失败时,Promise的状态会变为rejected,并返回一个错误信息。

基本语法

// 创建一个promise
let promise = new Promise(function(resolve, reject) {// 异步操作if (异步操作成功) {resolve(value); // 将异步操作的结果传递给Promise对象,状态变为fulfilled} else {reject(error); // 将异步操作的错误信息传递给Promise对象,状态变为rejected}
});promise.then(function(result) {// 异步操作成功时的处理代码
}).catch(function(error) {// 异步操作失败时的处理代码
});

常用方法

1.then

then中一般传入两个参数(函数),第一个对应resolve成功的回调,第二个对应reject失败的回调,如下

function onResolved(res) {
  console.log("resolved-" + res); // resolved-成功了
}
function onRejected(err) {
  console.log("rejected-" + err); // rejected-失败了
}
new Promise((resolve, reject) => {
  resolve('成功了');// reject('失败了')
}).then(onResolved, onRejected);

then的第二个参数就等同于catch方法,但是需要注意

  • Promise内部报错,reject抛出错误后,then的第二个参数和catch方法都存在的情况下,只有then的第二个参数能捕获到,如果then的第二个参数不存在,catch方法会捕捉到
  • catch不仅捕捉promise中抛出的错误,还会捕捉前面then中的错误

2.catch

捕捉promise错误函数,和then的第二个参数(函数)作用一样,处理错误,由于Promise抛出错误具有冒泡性质,能够不断传递,会传到catch中,所以一般来说所有错误处理放在catch中,then中只处理成功的,同时catch还会捕捉then中第一个参数(函数)抛出的异常

new Promise((resolve, reject) => {
  reject();
}).catch((err)=> {
  console.log(err)
});

3.finally

  • finally 方法没有参数,也不会改变 Promise 的状态,它只是在 Promise 结束时提供了一个通知机制,让我们可以在 Promise 结束后执行一些清理工作(比如操作文件的时候关闭文件流)。
  • Promise对象的finally()方法用于在Promise成功或拒绝时使用
  • 不管promise最后的状态,在执行完then或catch指定的回调函数以后,都会执行finally方法指定的回调函数,它可以防止Promise的then()和catch()方法中的代码重复。
// 栗子1
function onFinally() {
  console.log('结束');
}
new Promise((resolve, reject) => {}).finally(onFinally);

// 栗子2
let promise = new Promise((resolve,reject) => {
    resolve('resolve')
})
promise.then((res) => {
    console.log(res)
}).catch((err) => {
    console.log(err)
}).finally(()=> {
    console.log('this finally')
})
// resolve
// this finally

4.all

接受一个具有Iterable接口的类型,如数组,Map,Set,传入多个promise,
每一个promise执行成功resolve,最后才执行成功(返回一个Promise实例),进入then,否则失败进入catch

function p1() {
  var promise1 = new Promise(function (resolve, reject) {
      console.log("p1的第一条输出语句");
      resolve("p1完成");
  });
  return promise1;
}
function p2() {
  var promise2 = new Promise(function (resolve, reject) {
      console.log("p2的第一条输出语句");
      setTimeout(() => {
        console.log("p2的第二条输出语句");
        resolve("p2完成");}, 2000);
      });
      return promise2;
  }
}
function p3() {
  var promise3 = new Promise(function (resolve, reject) {
      console.log("p3的第一条输出语句");
      resolve("p3完成");
  });
  return promise3;
}
Promise.all([p1(), p2(), p3()]).then(function (data) { 
  console.log(data);
});// 输出
// p1的第一条输出语句;
// p2的第一条输出语句;
// p3的第一条输出语句;
// p2的第二条输出语句[("p1完成", "p2完成", "p3完成")];
var p1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 1000, 'one');
});
var p2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 2000, 'two');
});
var p3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 3000, 'three');
});
var p4 = new Promise((resolve, reject) => {
  setTimeout(resolve, 4000, 'four');
});
var p5 = new Promise((resolve, reject) => {
  reject('reject');// setTimeout(resolve, 5000, 'five');
});
Promise.all([p1, p2, p3, p4, p5]).then(values => {
  console.log(values); // [ 'one', 'two', 'three', 'four', 'five' ]
}, reason => {
  console.log(reason) // reject
});

5.allSettled

接受一个具有Iterable接口的类型,如数组,Map,Set,传入多个promise,
每个promise状态改变成fulfilled或者rejected之后返回,返回的是一个数组对象,对象中有状态status和每一项的返回结果value

Promise.allSettled([p1, p2, p3, p4, p5]).then(values => {
  console.log(values);
}, reason => {console.log(reason)
});
// [
//   { status: 'fulfilled', value: 'one' },
//   { status: 'fulfilled', value: 'two' },
//   { status: 'fulfilled', value: 'three' },
//   { status: 'fulfilled', value: 'four' },
//   { status: 'rejected', reason: 'reject' }
// ]

6.race

以快为准,数组中所有的promise对象,有一个先执行了何种状态,该对象就为何种状态,并执行相应函数
接受一个具有Iterable接口的类型,如数组,Map,Set,传入多个promise,
其中有一个promise返回了,不管是fulfilled或者rejected,直接返回这个promise的结果

function p1() {
  var promise1 = new Promise(function (resolve, reject) {
      console.log("p1的第一条输出语句");
      resolve("p1完成");
  });
  return promise1;
}
function p2() {
  var promise2 = new Promise(function (resolve, reject) {
      console.log("p2的第一条输出语句");
      setTimeout(() => {
        console.log("p2的第二条输出语句");
        resolve("p2完成");
      }, 2000);
  });
  return promise2;
}
function p3() {
  var promise3 = new Promise(function (resolve, reject) {
    console.log("p3的第一条输出语句");
    resolve("p3完成");
  });
  return promise3;
}
Promise.race([p1(), p2(), p3()]).then(function (data) {
  console.log(data);
});// 输出
// p1的第一条输出语句
// p2的第一条输出语句
// p3的第一条输出语句
// p1完成

7.any

接受一个具有Iterable接口的类型,如数组,Map,Set,传入多个promise,
当传入的任何一个promise成功的时候,不管其他是否成功或者失败,会把成功的那个promise返回

如果传入的是一个空的数组(Map,Set),返回一个已失败状态的promise,如下

注意
Promise的以上方法都属于 微任务。当Promise状态变为已解决(resolved)或被拒绝(rejected)时,这些方法会产生微任务。这些微任务会在主线程空闲时按照顺序依次执行。

3. 有什么问题

  • 首先,无法取消 Promise,一旦新建它就会立即执行,无法中途取消。
  • 其次,如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。
  • 第三,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
posted @ 2023-05-25 11:12  seekHelp  阅读(1174)  评论(0)    收藏  举报