Promise知识梳理

Promise是什么?

通俗来讲,Promise就是一个用于保存异步操作的容器。当一个异步操作完成后,它要么保存了值,要么保保存了错误的信息。Promise基本上就是“承诺”你它会给你一个异步操作的结果。

这个对象分为三个阶段:

  • pending阶段,创建promise对象时,处于挂起状态,关联某个异步操作。
  • Fullfilled阶段,表示promise有结果将被履行,异步操作成功完成,有结果了。
  • Rejected阶段,表示异步操作过程中出现问题,被拒绝了,得到错误值。

首先创建一个Promise对象,这个构造函数需要一个参数,这个参数是一个需要两个参数的函数。分别是resolvereject两个参数的匿名函数

const p = new Promise((resolve,reject) => {
    //成功后执行的函数
    resolve('hello')
    //失败后执行的函数
    reject(new Error('message'))
}) 
复制代码

我们平常查询一个数据库,请求一个网络服务或者设置一个延时执行的程序都会用到异步操作,而promise对象也就非常适合这些场合使用。

因为使用了promise,所以后面一定会给我们一个异步操作的结果,不论是成功的函数失败的。所以我们需要将值返回给promise的使用者,我们就用上面的resolvereject参数来实现。

假设上面的异步操作完成了,执行的结果就是“hello”。在现实编程中,这个“hello”也可以是一个从数据库中读取的信息,这就是异步操作的结果。现在我们需要兑现了,因为后续可能使用了p对象。看它有两个方法。

catch用于获取任何的报错, then用来获取异步操作成功的返回值,我们调用 then,然后传入一个函数。这里我们传入 result,就是里面的 resolve函数。

const p = new Promise((resolve, reject) => {
  //成功后执行的函数
  resolve("hello");
  //失败后执行的函数
  reject(new Error("message"));
});

p.then(result => console.log("result", result));
复制代码

打开控制台,运行promise.js

我们得到了结果: hello,很好,再次改造下添加一个定时器,实现异步操作。

const p = new Promise((resolve, reject) => {
  //成功后执行的函数
  setTimeout(() => resolve("hello"), 2000);
  //失败后执行的函数
  // reject(new Error("message"));
});

p.then(result => console.log("result", result));
复制代码

再次运行,可以看到间隔2秒后返回了结果。

当然我们也提到,如果有错误了,那么将会把 error返回给调用者,最后链接上 catch,当遇到什么问题的时候可以了解到具体的错误是什么。

const p = new Promise((resolve, reject) => {
  //成功后执行的函数
  setTimeout(() => {
    // resolve("hello");
    reject(new Error("message"));
  }, 2000);
});

p.then(result => console.log("result", result)).catch(err =>
  console.log("Error", err.message)
);
复制代码

这次我们再运行程序,将会得到错误信息,因为我们“拒绝”履行承诺。

现在总结一下,Promise是一个对象,用于保存异步操作的任何结果,当我们创建对象的时候进入了挂起的状态。上面的代码就是它开始处理一个异步操作,这个操作有可能成功也可能失败。

如果成功了,我们就说承诺“解决”了,或者是被履行了。Promise的状态由挂起转为解决或者履行,我们就用resolve函数返回结果给调用者。

如果异步操作失败了,Promise的状态由挂起转为拒绝,我们就用reject函数返回一个错误给调用者。

这就是如何创建一个Promise,然后是如何使用它。我们使用then来得到结果,catch来捕捉错误对象。有一点需要提到的是如果在任何地方用到了异步的回调,都应该让函数返回一个Promise

Promise并行操作是什么?

有时我们可能想要并行的处理几个异步请求,当它们全部结束后再做点什么。比如可能同时请求两个或以上网站的API,当所有的请求都完毕的时候就可以返回什么给客户端了。

首先创建两个Promise对象,这里我们需要返回结果,不要被拒绝,所以就一个参数。

const p1 = new Promise(resolve => {
  setTimeout(() => {
    console.log("异步操作1");
    resolve(1);
  }, 2000);
});

const p2 = new Promise(resolve => {
  setTimeout(() => {
    console.log("异步操作2");
    resolve(2);
  }, 2000);
});
复制代码

现在我想同时处理这两个请求,当它们都完成的时候我们再做些什么。这里调用Promise.all(),这是另一个Promise类的静态方法,而不是Promise对象的实例方法。然后传入一个Promise对象的数组,这里是p1p2,将会返回一个新的Promise。它的履行取决于所有包含Promise对象全部履行。先调用这个Promise,然后调用then,将结果显示在控制台。

Promise.all([p1, p2]).then(result => console.log(result));
复制代码

可以看到两个都执行了,得到了两个结果组成的数组。

如果其中一个Promise对象失败了呢?我们修改第一个Promise,让它有reject参数

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log("异步操作1");
    reject(new Error("出现错误了"));
  }, 2000);
});

const p2 = new Promise(resolve => {
  setTimeout(() => {
    console.log("异步操作2");
    resolve(2);
  }, 2000);
});

Promise.all([p1, p2])
  .then(result => console.log(result))
  .catch(err => console.log("Error", err.message));
复制代码

再次运行查看,只要其中一个Promise出错了,全部Promise的最终返回值都会被拒绝。

如果只要其中有 Promise实现了就立即进行某些操作,而不是等到所有全部履行。这样的话可以使用 race方法取代 all

const p1 = new Promise(resolve => {
  setTimeout(() => {
    console.log("异步操作1");
    resolve(1);
  }, 2000);
});

const p2 = new Promise(resolve => {
  setTimeout(() => {
    console.log("异步操作2");
    resolve(2);
  }, 2000);
});

Promise.race([p1, p2])
  .then(result => console.log(result))
  .catch(err => console.log("Error", err.message));
复制代码

这样只要其中一个 Promise履行,就可以拿到结果。

Async/Await是什么?

在现在的JavaScript中有个新特性,asyncawait,这可以让你写同步代码一样写异步代码。

function getUser(id) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log("读取id中...");
      resolve({
        id: id,
        gitHubUsername: "mosh"
      });
    }, 2000);
  });
}

function getRepositories(username) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log("获取用户信息中...");
      resolve(["repo1", "repo2", "repo3"]);
    }, 2000);
  });
}

function getCommits(text) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log("获取内容中...");
      resolve(["hello"]);
    }, 2000);
  });
}
复制代码

要注意的是使用Async/Await,在Promise中我们使用try-catch块来捕捉异常,它没有catch方法。在这个函数中,我们将所有的异步操作代码包含到try块中,然后是catch块。捕捉到的是err对象。如果有异常,catch块的代码就执行。

async function displayCommits() {
  try {
    const user = await getUser(1);
    const repos = await getRepositories(user.gitHubUsername);
    const commits = await getCommits(repos[0]);
    console.log(commits);
  } catch (err) {
    console.log("Error", err.message);
  }
}
displayCommits();
复制代码

还是在控制台执行:

转载于:https://juejin.im/post/5c8b484d518825493a0b5a6a

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值