Promise 是 ES6 的新特性,提供了对 js 异步编程控制的新的解决方案,在过去书写异步代码时要靠回调函数,当异步操做依赖于其余异步操做的返回值时,会出现一种现象,被程序员们称为 “回调地狱”,即多层回调函数嵌套,这种代码的可读性、维护性都不好,所以诞生了 Promise,固然 Promise 并非彻底摆脱回调,而只是改变了传递回调的位置,大大减小了回调函数嵌套。程序员
<br/>编程
Promise 中的代码默认是同步执行的,then
方法中的回调在微任务队列中执行,在 Promise 的 then
方法中支持传入两个参数,一个是成功的回调,一个是失败的回调,在 Promise 中调用了 resolve
方法,就会在 then
中执行成功的回调,调用了 reject
方法,就会在 then
中执行失败的回调,成功的回调和失败的回调只能执行一个,resolve
和 reject
方法调用时传入的参数会传递给 then
方法中对应的回调函数。数组
// 执行 resolve let p = new Promise((resolve, reject) => { console.log(1); resovle(3); }); console.log(2); p.then(data => { console.log(data); }, err => { console.log(err); }); // 1 // 2 // 3
// 执行 reject let p = new Promise((resolve, reject) => { reject(); }); p.then(() => { console.log(1); }, () => { console.log(2); }); // 2
若是 Promise 中发生错误,就会在 then
中执行失败的回调。异步
// 失败的回调 let p = new Primise((resolve, reject) => { throw new Error(); }); p.then(() => { console.log(1); }, () => { console.log("报错啦"); }); // 报错啦
当同一个 Promise 实例的 then
方法屡次调用时,就会屡次执行。异步编程
// 屡次调用 then let p = new Promise((resolve, reject) => { resolve("成功"); }); p.then(data => { console.log(data); }); p.then(data => { console.log(data); }); // 成功 // 成功
Promise 支持链式调用,每次调用一次 then
方法都会返回一个新的 Promise实例,若是该 then 方法中执行的回调函数有返回值,而且这个返回值会做为返回的下一个 Promise 实例的 then
方法回调的参数,若是 then
方法的返回值是一个 Promise 实例,那就返回一个新的 Promise 实例,将 then
返回的 Promise 实例执行后的结果做为返回 Promise 实例回调的参数。函数
// 链式调用 then function read(url) { return new Promise((resolve, reject) => { fs.readFile(url, "utf8", (err, data) => { if (err) reject(err); resolve(data); }) }); } read("1.txt").then(data => { // 假设此时读到的内容为 Hello world return data; }, err => { console.log(err); }).then(data => { console.log(data); // Hello world }, err => { console.log(err); }); read("1.txt").then(data => { // 假如此时读到的 1.txt 的内容为 2.txt 的字符串,2.txt 的内容为 Hello world return read(data); }, err => { console.log(err); }).then(data => { console.log(data); // Hello world }, err => { console.log(err); });
在 Promise 实例的 then
中若是有错误产生,在返回的新的 Promise 实例中的 then
方法中会执行错误的回调。this
// 链式调用 then 出错 let p = new Promise((resolve, reject) => { resolve(); }); p.then(() => { console.log("success", 1); throw new Error(); }, () => { console.log("error", 1); }).then(() => { console.log("success", 2); }, () => { console.log("error", 2) }) // success 1 // error 2
在 Promise 中有三个状态:url
Promise 实例的状态只能从 pending
到 fulfilled
或从 pending
到 rejected
,状态一旦发生变化就不可逆,因此 Promise 实现链式调用与 jQuery 不一样,返回的不是 this
,只能是一个新的 Promise。spa
在 Promise 中实例的 catch
方法能够捕获链式调用中的异常,不须要每次调用 then
方法中都传入错误的回调,在链式调用的过程当中只要有任何一个 then
中出现错误,都会被 catch
方法捕获到。code
// catch 方法 let p = new Promise((resolve, reject) => { resolve(); }); p.then(() => { throw new Error(); console.log("success", 1); }).then(() => { console.log("success", 2); }).catch(() => { console.log('出错了'); }); // 出错了 p.then(() => { console.log("success", 1); }).then(() => { throw new Error(); console.log("success", 2); }).catch(() => { console.log('出错了'); }); // success 1 // 出错了
Promise 中的静态方法 all
能够实现多个 Promise 实例的并行,当全部结果都为成功时,返回一个数组,该数组存储的为每个 Promise 实例的返回结果,每个 Promise 实例的返回顺序前后不固定,可是返回值的数组内存储每个 Promise 的返回值的结果按照最初传入的顺序排列,all
方法的返回值为一个新的 Promise 实例,返回的数组做为返回新 Promise 的 then
方法成功回调的参数。
当 all
传入的参数数组中的 Promise 实例执行时,只要有一个失败,则直接返回该 Promise 实例失败的结果或错误信息。
// Promise.all 方法 let p1 = new Promise((resolve, reject) => { resolve(1); }); let p2 = new Promise((resolve, reject) => { resolve(2); }); Promise.all([p1, p2]).then(data => { console.log(data); }); // [1, 2]
// Promise.all 错误捕获 let p1 = new Promise((resolve, reject) => { resolve(1); }); let p2 = new Promise((resolve, reject) => { reject(2); }); Promise.all([p1, p2]).then(data => { console.log(data); }).catch(err => { console.log(err); }); // 2
Promise 的静态方法 race
的用法和 all
相似,参数同为一个存储 Promise 实例的数组,返回值一样是一个新的 Promise 的实例,不一样的是,数组中的 Promise 实例只有一个结果为成功,那就直接返回这个结果(只取出最快返回的结果),在没有成功的结果以前有一个出错,就直接返回这个错误。
// Promise.race 方法 let p1 = new Promise((resolve, reject) => { setTimeout(() => resolve(1), 2000); }); let p2 = new Promise((resolve, reject) => { setTimeout(() => resolve(2), 1000); }); Promise.race([p1, p2]).then(data => { console.log(data); }).catch(err => { console.log(err); }); // 2
// Promise.race 错误捕获 let p1 = new Promise((resolve, reject) => { setTimeout(() => reject(1), 1000); }); let p2 = new Promise((resolve, reject) => { setTimeout(() => resolve(2), 2000); }); Promise.race([p1, p2]).then(data => { console.log(data); }).catch(err => { console.log(err); }); // 1
Promise 的静态方法 resolve
能够直接将 Promise 的状态变为成功并返回一个新的 Promise 实例,resolve
的参数会传递给返回的新 Promise 实例 then
中成功回调。
// Promise.resolve 方法 Promise.resolve('hello').then(data => { console.log(data); }); // hello
Promise 的静态方法 reject
与 resolve
使用彻底相同,都返回一个新的 Promise 实例,不一样的是 reject
的参数会传递给新 Promise 实例的 then
方法失败回调。
// Promise.reject 方法 Promise.reject('出错了').then(null, err => { console.log(err); }); // 出错了
当成功的回调不传递时,可使用 null
代替,由于 null
做为参数会被忽略掉,将参数穿透到下一个 then
的回调中。