Promise知识梳理

Promise是什么?

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

这个对象分为三个阶段:数据库

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

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

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

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

由于使用了promise,因此后面必定会给咱们一个异步操做的结果,不管是成功的函数失败的。因此咱们须要将值返回给promise的使用者,咱们就用上面的resolvereject参数来实现。promise

假设上面的异步操做完成了,执行的结果就是“hello”。在现实编程中,这个“hello”也能够是一个从数据库中读取的信息,这就是异步操做的结果。如今咱们须要兑现了,由于后续可能使用了p对象。看它有两个方法。 bash

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是一个对象,用于保存异步操做的任何结果,当咱们建立对象的时候进入了挂起的状态。上面的代码就是它开始处理一个异步操做,这个操做有可能成功也可能失败。async

若是成功了,咱们就说承诺“解决”了,或者是被履行了。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();
复制代码

仍是在控制台执行:

相关文章
相关标签/搜索