1.Promise
说明:Promise是异步编程的一种解决方案。简而言之,也就是存者未来发生的事件的容器。 Promise提供统一的API,各种异步操作都可以用同样的方法进行处理。
特点:对象的状态不受外界影响。Promise对象代表一个异步操作,存在三种状态:pending(进行时),fulfilled(已成功),rejectted(已失败),一旦状态改变,就不会再改变。
缺点:一旦创建它就会立即执行,无法取消。如果不设置回调函数Promise内部抛出的错误,不会反应到外部。
2.基本使用
说明: ES6规定,Promise对象是一个构造函数,用来生成Promise实例。
const p1 = new Promise(function (resolve, reject) {if (true) {resolve() //异步成功} else {reject() //异步失败}})
说明:Promise函数接受的函数作为参数,该函数有两个参数,分别为resolve, reject。它们也是两个函数,有JavaScript引擎提供,不用自己写。resolve函数的作用是在异步操作成功时调用,并将异步的结果传递出去,reject函数的作用是在异步操作失败是调用,并将异步操作报出的错误,作为参数传递出去。Promise实例生成后,then方法可以接受两个回调函数。第一个回调函数是romise对象的状态变为成功(resolved)时调用,第二个回调函数时Prmise对象的状态变成失败(rejected)时调用。两个函数时可选的,它们都接受Promise对象传出的值作为参数。
3.异步加载图片
3.1例子
function loadImageAsync(url) {return new Promise(function (resolve, reject) {const image = new Image()image.onload = function () {// 在图像加载完成后执行的操作resolve(image)}image.onerror = function () {// 加载图像时可能发生的错误reject(new Error("加载图像时可能发生错误" + url))}})}
3.2例子
const p2 = new Promise((resolve, reject) => {setTimeout(() => {return reject(5)}, 2000);})p2.then((resolve, reject) => {console.log(resolve);// 所以reject函数可以省略,因为catch会捕获console.log(reject);}).catch(err=>{// .catch 方法的作用是捕获 Promise 执行过程中出现的错误,并对其进行处理。// console.log(err);})
4.Pomise.prototype.then方法
说明: Promise实例具有then方法,也就是说方法时定义在原型对象上的。then方法的第一个参数时resolved状态的。回调函数,第二个参数时rejected状态的回调函数,它们都是可选的。 then方法返回的是一个新的Promise实例(不是原来那个Promise实例)。catch方法也是返回一个新的Promise实例。
getJSON("./1.josn").then(function(){return 1}).then(resolve=>{return console.log("成功回调");},error=>{return console.log(error.message);})
5.Promise.prototype.catch方法
说明:本方法其实就是.then(null,rejection)或.then(undefined,rejection)的别名,用于指定发生错误的回调函数。当异步操作抛出错误,状态就会变成rejected,就会调用catch()方法指定的回调函数,处理这个错误。另外,then()方法指定的回调函数,如果运行中抛出错误,也会被catch()方法捕获。
5.1例子
p.then(value=>{return console.log(value);}).then((null,error=>{console.log("rejected");}))// 等价于p.then(value=>{return console.log(value);}).catch(err=>{return console.log(err);})
5.2例子
const p3=new Promise((resolve,reject)=>{throw Error("发生错误")})p3.then(resolve=>{console.log(resolve);}).catch(error=>{console.log(error);}) //Error: 发生错误 */
说明: Promise 对象的错误具有冒泡性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获。一般来说,不要在then()方法里面定义Reject状态的回调函数(then的第二个参数),总是用catch方法捕获。
6. Promise.prototype.finally方法
说明: finally()方法用于指定不管Promise对象最后状态如何,都会执行。
const p4=new Promise((resolve,reject)=>{resolve(5)})p4.then(value=>{// 成功执行console.log(value); //5}).catch(error=>{// 失败执行,打印错误console.log(error.message);}).finally(()=>{// 一直会执行的console.log("FOREVER"); //FOREVER})
7.Promise.all方法
说明: Promise.all()方法用于将多个Promise实例,包装成一个新的Promise实例。
const p5=Promise.all([p1,p2,p3]) //此行代码中p开头的都是Promise对象的实例
注意:
- 只有所有的Promise实例对象都成功,将返回值组成一个数组,传递给p的回调函数
- 只有所有的Promise实例对象都失败,此时第一个被reject的实例的返回值,会传递给p的回调函数。
8.Promise.race方法
const p1 = new Promise((resolve, reject) => {setTimeout(() => {resolve(5)}, 5000);})// 上述代码将在5秒后,将会调用resolve()方法const p2 = new Promise((resolve, reject) => {setTimeout(() => {reject(new Error("回调失败"))}, 3000);})// 上诉代码将在3秒后,将会调用reject()方法const allp = Promise.race([p1, p2])allp.then(success => {console.log(success);}).catch(error => {console.log(error); //Error: 回调失败})
说明:代码中只要p1,p2实例率先改变状态,p的状态就跟着改变,率先改变的Promise实例的返回值,就传递给p的回调函数。
9.Promise.allSettled方法
说明:确定异步函数操作是否都已经结束了,包含resolve()和reject()方法。
const p3 = new Promise((resolve, reject) => {setTimeout(() => {resolve(5)}, 2000);})// 上述代码将在2秒后,将会调用resolve()方法const p4 = new Promise((resolve, reject) => {setTimeout(() => {reject(new Error("回调失败"))}, 1000);// 同上})const allp1 = Promise.allSettled([p3, p4])allp1.then(success => {console.log(success);}).catch(error => {console.log(error);})/* 0: {status: "fulfilled", value: 5}1: {status: "rejected", reason: Error: 回调失败 */
注意:本方法返回的新的Promise实例,一旦发生状态改变,状态总是fulfulled(成功),因此可以不用是catch捕获错误的信息 回调函数接收到的参数是数组success。success的每个成员是一个对象,对象的格式是固定的,对应异步操作的结果。
10.Promise.any方法
说明: Promise.any()跟Promise.race()方法很像,不同的是Promise.any()不会因为某个Promise变成rejected状态而结束,必须等到所有的参数Promise变成rejected状态才会结束。
const p5 = new Promise((resolve, reject) => {setTimeout(() => {resolve(5)}, 2000);})// 上述代码将在2秒后,将会调用resolve()方法const p6 = new Promise((resolve, reject) => {setTimeout(() => {reject(new Error("回调失败"))}, 1000);// 同上})const p7 = new Promise((resolve, reject) => {setTimeout(() => {reject(new Error("回调失败"))}, 1000);})const allp2 = Promise.any([p5, p6, p7])allp2.then(success => {console.log(success); //5}).catch(error => {console.log(error);})
注意:只要参数实例有一个变成成功状态,包装实例就会变成功的状态,如果实例都变成了失败状态,包装实例就会变成失败状态。
11.Promise.resolve方法
说明:有时候将现有对象转成Promise对象,Promise.resolve()方法就起到了这个作用。
Promise.resolve("successValue")等价于new Promise((resolve,reject)=>{resolve(5)})
11.1例子
const p8 = Promise.resolve("5")p8.then(success => {console.log(success); //5}).catch(error => {console.log(error);})
12.Promise.reject
说明:Promise.reject()方法也会返回一个新的Promise实例,状态为失败。
const p9 = Promise.reject("失败")p9.then(success => {console.log(success);}).catch(error => {console.log(error); //失败})
13.应用
说明:我们可以将图片的加载写成了Promise,加载完成Promise的状态就发生了变化。
// 声明一个加载函数const preloadImage = function (path) {return new Promise((resolve, reject) => {const image = new Image()image.onload = resolveimage.onerror = rejectimage.src = path})}