Promise
是什么?通俗来说,Promise
就是一个用于保存异步操做的容器。当一个异步操做完成后,它要么保存了值,要么保保存了错误的信息。Promise
基本上就是“承诺”你它会给你一个异步操做的结果。git
这个对象分为三个阶段:数据库
pending
阶段,建立promise
对象时,处于挂起状态,关联某个异步操做。Fullfilled
阶段,表示promise
有结果将被履行,异步操做成功完成,有结果了。Rejected
阶段,表示异步操做过程当中出现问题,被拒绝了,获得错误值。首先建立一个Promise
对象,这个构造函数须要一个参数,这个参数是一个须要两个参数的函数。分别是resolve
和reject
两个参数的匿名函数编程
const p = new Promise((resolve,reject) => {
//成功后执行的函数
resolve('hello')
//失败后执行的函数
reject(new Error('message'))
})
复制代码
咱们日常查询一个数据库,请求一个网络服务或者设置一个延时执行的程序都会用到异步操做,而promise
对象也就很是适合这些场合使用。数组
由于使用了promise
,因此后面必定会给咱们一个异步操做的结果,不管是成功的函数失败的。因此咱们须要将值返回给promise
的使用者,咱们就用上面的resolve
和reject
参数来实现。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
对象的数组,这里是p1
,p2
,将会返回一个新的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
中有个新特性,async
和await
,这可让你写同步代码同样写异步代码。
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();
复制代码
仍是在控制台执行: