• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

【JS】ES6中的Promise

武飞扬头像
juejin
帮助84

Promise

Promise是异步编程的解决方案,在Promise没有出现之前,是通过回调函数来解决异步的问题。

它是一个对象,里面保存着未来才会结束的事件,可以从这里面获取异步操作的信息。

状态

Promise共有三种状态,分别是

  • pending 进行中
  • fulfilled 完成
  • rejected 失败

你可以在任何时候获取当前promise状态,promise状态的改变只有两种可能:pending=>filfilledpending=>rejected。当状态发送改变之后,就不会再次改变了。

例子

我们从一个例子来认识Promise吧,它是一个构造函数,用来生成Promise实例。

const p = new Promise();

Promise中需要传入一个函数,且这个函数需要接受两个参数分别是resolve函数和reject函数,resolve函数用于将Promise对象的状态从pending修改成fulfilled,并将成功的结果作为参数返回出去。resolve函数用于将Promise对象的状态从pending修改成rejected,并将错误信息作为参数返回出去。

在调用resolvereject函数时有传入参数,这些参数会被传递给回调函数

我们把前面的例子,加入setTimeout模拟异步操作。当msg变量的值为_island时调用resolve(),否则调用reject()

const p = new Promise((resolve, reject) => {
  const msg='_island'
  setTimeout(() => {
    if(msg==='_island'){
      resolve("执行成功");
    }else{
      reject()
    }
  }, 2000);
});

Promise对象生成时候,我们就可以通过.then方法,获取当前异步操作对应的结果。

p.then((result)=>{
  console.log('成功的状态');
  console.log(result);
},(err)=>{
  console.log('失败的状态');
  console.log(err);
})

// 成功的状态
// 执行成功

在调用resolvereject方法之后,Promise的任务就完成了,后续的操作应该放在then方法里面去操作。

(建议在resolvereject方法的前面加上return关键字)

then

Promise.then()方法是返回一个新的Promise实例(不是原来的promise实例),因此可以使用链式语法.then操作。

下面这个例子,使用了两次.then方法,在第一个回调函数中返回结果作为第二个回调函数的参数。

p.then((result)=>{
  console.log('成功的状态');
  console.log(result);
  return result
},(err)=>{
  console.log('失败的状态');
  console.log(err);
}).then((result)=>{
  console.log(result);
})

// 成功的状态
// 执行成功
// 执行成功

catch

Promise.catch()方法用于指定发生错误时的回调函数,它是then中的传入的第二个参数的别名。和then一样,返回一个Promise对象,后面可以继续.then

通常,我们不在then之中定义reject回调函数,建议使用catch方法来捕捉错误。

p.then((result)=>{
  console.log('成功的状态');
  console.log(result);
  return result
}).catch((err)=>{
  console.log(err);
})
 
// 执行失败

finally

Promise.finally()方法,无论Promise对象最后的状态是什么样的,都会执行对应的函数。

p.then((result)=>{
  console.log('成功的状态');
  console.log(result);
  return result
}).catch((err)=>{
  console.log(err);
}).finally(()=>{
  console.log('无论什么状态,我都会被执行');
})
 
// 执行失败

all

Promise.all()方法用于将多个Promise实例包装成一个新的Promise实例。它接收一个Promise的数组或者是一个具有Iterator接口。

下面这个例子,ps数组中包含了p1p2p3 三个promise实例,使用all方法包装成一个新的Promise实例。

const p1 = new Promise((resolve) => {
  setTimeout(() => {
    resolve("p1");
  }, 2000);
});
const p2 = new Promise((resolve) => {
  setTimeout(() => {
    resolve("p2");
  }, 3000);
});
const p3 = new Promise((resolve) => {
  setTimeout(() => {
    resolve("p3");
  }, 1000);
});

const ps = [p1, p2, p3];

这个包装出来的Promise对象(ps)的状态由传入的p1p2p3的状态而决定。当这三个Promise实例的状态为fulfilled时,它们的返回值会被存放到一个数组中,返回给ps的回调函数。如果某一个Promise实例的状态为rejected时,就会把reject的实例返回值传递给ps的回调函数

Promise.all(ps).then((res) => console.log(res)); // [ 'p1', 'p2', 'p3' ]

resolve

Promise.resolve方法用于将一个对象转为Promise对象。

const obj = {
  name: "_island"
};

const pobj = Promise.resolve(obj);
console.log(pobj); // Promise { { name: '_island' } }

上面这种写法相当于下面这种写法

const pobj = new Promise((resolve) => resolve(obj));
边界情况
  • 如果参数是Promise对象,则不做修改,直接返回传入的这个参数
  • 如果被包装的对象中包含then方法,Promise.resolve()方法将在包装完的这个对象之后执行对象中的then方法
  • 如果传入的不是一个对象或者不带有参数,Promise.resolve()方法将返回一个新的Promise对象,状态为resolved

reject

Promise.reject()方法用于返回一个新的Promise实例,该实例的状态为rejected

const p = Promise.reject("报错了");
// 等价下面这一行代码
const p = new Promise((null, reject) => reject("报错了"));

搭配catch方法使用,得到参数是上面reject传入的参数。

const p = Promise.reject("报错了").catch(e=>console.log(e));
// 报错了

race

Promise.race()方法和Promise.all方法类似,同样是将多个Promise实例包装出一个新的Promise实例。

const p1 = new Promise((resolve) => {
  setTimeout(() => {
    resolve("p1");
  }, 2000);
});
const p2 = new Promise((resolve) => {
  setTimeout(() => {
    resolve("p2");
  }, 3000);
});
const p3 = new Promise((resolve) => {
  setTimeout(() => {
    resolve("p3");
  }, 1000);
});
​
const ps=Promise.race([p1,p2,p3])
ps.then(res=>console.log(res))
// p3

上面的代码,ps的状态也是根据p1p2p3的状态而决定的,当这三个Promise实例中其中有一个状态发生改变时,ps的状态就会将这个实例的返回值处理给ps的回调函数,所以结果是p3(如果返回值不是Promise实例,则调用先Promise.resolve再处理)

allSettled

Promise.allSettled()方法返回一个一组已完成、已失败状态的promise实例,并带有一个对象数组,每个对象表示对应的Promise结果。(这是ES2020引入的新方法)

const p1 = new Promise((resolve) => {
  setTimeout(() => {
    resolve("p1");
  }, 2000);
});
const p2 = new Promise((resolve,reject) => {
  setTimeout(() => {
    reject("p2");
  }, 3000);
});
const p3 = new Promise((resolve,reject) => {
  setTimeout(() => {
    reject("p3");
  }, 1000);
});
​
const ps=Promise.allSettled([p1,p2,p3])
ps.then(res=>console.log(JSON.stringify(res)))
// [
//   {"status":"fulfilled","value":"p1"},
//   {"status":"rejected","reason":"p2"},
//   {"status":"rejected","reason":"p3"}
// ]

从上面代码的返回值可以看出返回到的是数组,里面存放着每个结果的对象,status代表promise实例的状态结果,当状态是fulfilled时,对应的属性是value,如果是rejected,则对应的是一个reason属性。

any

Promise.any()方法将多个Promise实例包装成一个新的Promise实例,只要其中某一个Promise实例返回fulfilled状态这个any方法就结束了,不会等待其他Promise实例(这是ES2021引入的新方法)

const p1 = new Promise((resolve) => {
  setTimeout(() => {
    resolve("p1");
  }, 100);
});
const p2 = new Promise((resolve,reject) => {
  setTimeout(() => {
    resolve("p2");
  }, 3000);
});
const p3 = new Promise((resolve,reject) => {
  setTimeout(() => {
    resolve("p3");
  }, 1000);
});
Promise.any([p1,p2,p3]).then(res=>console.log(res))
// p1

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanekgh
系列文章
更多 icon
同类精品
更多 icon
继续加载