Promise函数详解:https://blog.csdn.net/weixin_34204722/article/details/87961589
一、Promise的概述
Promise承诺的意义:
可以解决传统回调函数嵌套导致代码混乱不易读的问题,Promise函数可以将传统嵌套的回调函数变成一种平行结构。
是一种异步编程的解决办法,比传统的解决方案更合理更强大。
Promise对象代表一个异步操作,有三种状态:pending进行中、fulfilled(resolve)成功、reject失败。
二、Promise对象有以下两个特点:
1.对象的状态不受外界影响,除非改变内部的状态。
2.一旦状态设定,就不会再变,任何时候都可以得到这个结果。并且Promise状态发生改变只有两种可能:1.从pending到resolve;2.从pending到reject。
三、Promise原型下面有三个重要的方法:
then((resolve返回的参数) => {}) Promise成功状态执行内部函数; catch((reject返回的参数) => {}) Promise失败状态执行内部函数; finally(() => {})无论成功与否都会执行该方法。//then 和 catch 方法中得到的参数是上面Promise对象成功失败状态后面括号中的数据,并且这两个方法都会返回Promise对象本身。
创建一个Promise对象
let p1 = new Promise((resolve,reject) => {
resolve(‘success’); // 成功状态
reject(‘fail’); // 失败状态
})
需要注意,Promise对象中可以存在多种状态,但是只有第一个状态会生效,并且设定后就无法改变,所以上面的Promise的状态就是成功,后面设定的失败状态无效。
调用then方法
p1.then((str) => {
console.log(str); // success
});
调用catch方法
p1.catch((str) => {
console.log(str); // 浏览器报错,因为Promise的状态已经被我们设定为成功,所以无法执行catch方法
})
链式调用
p1.catch((str) => {
console.log(str);
}).then((str) => {
console.log(str);
}); //success,本来catch语句应该会报错,但是链式调用会在第一个方法失败后继续调用后面的方法,直到调用到对应状态的方法为止,链式调用是使用了catch和then会返回Promise对象本身这一特点达成的。
resolve状态的返回值只会给第一个then方法 reject状态的返回值只会给第一个catch方法我们还可以手动传递一个Promise对象给链式操作的下一个方法
p1
.then((d) => {
console.log(d); //输出success,p1的状态执行它
return new Promise((resolve, reject) => {
resolve('success123');
});
})
.then((d) => { //success123,这里的参数值是上面的then里面的状态传下来值。
console.log(d);
return new Promise((resolve, reject) => {
resolve('success123456');
});
})
.then((d) => {
console.log(d); //success123456 这里的d必须依靠上面的then里面的状态传下来。
});
Promise.prototype.finally(ES9 2018年新增)
finally方法用于指定不管Promise对象最后状态如何,都会执行的操作,该方法是ES2018(ES9)引入标准的。
finally方法不是必须的,可以省略不写。
let p1 = new Promise((resolve, reject) => { //resolve:成功的回调 reject:失败的回调
eject(‘error’);
});
p1.then((d) => {
console.log(d);
}).catch((e) => {
console.log(e);
}).finally(() => {
console.log(‘finally一定会执行的’);
});
四、Promise对象的静态方法
1.Promise.all() :用于将多个Promise实例,包装成一个新的Promise实例,接受一个数组作为参数,只有数组里的所有实例的状态都变成resolve,新的Promise实例状态才会变成resolve。
创建一个Promise对象
function $ajax(url) {
return new Promise((resolve,reject) => {
let xhr = new XMLHttpRequest();
xhr.open(‘get’, url, true);
xhr.send();
xhr.onload = function() {
if(xhr.readyState === 4) {
if(xhr.status === 200) {
resolve(xhr.responseText);
} else {
reject(‘接口地址错误’)
}
}
}
});
}
包装一个新Promise实例对象
let newPromise = Promise.all([
$ajax(‘http://localhost/JS2204(2203)/week05/Day26_ajax/code/taobaoapi.php/week05/Day26_ajax/code/taobaoapi.php)’),
]); //将三个Promise实例作为参数放进这个新Promise实例中。
获取三个接口的值,如果这三个Promise任意一个接口报错都会导致所有接口都无法读取,并报错。
new Promise.then((e) => {
console.log(e);
}).catch((e) => {
console.log(e);
});
2.Promise.race() :这个方法同样是将多个Promise实例,包装成一个新的Promise实例,接受一个数组作为参数,只要其中一个实例率先改变状态,则整个的状态就跟着改变。哪个实例的状态先改变,就跟着该实例改变自身状态。
//创建三个Promise对象
let p1 = new Promise((resolve,reject) => {
setTimeout(() => {
resolve(第一个状态);
}, 2000);
});
let p2 = new Promise((resolve,reject) => {
setTimeout(() => {
reject(第二个状态);
}, 500);
});
let p3 = new Promise((resolve,reject) => {
setTimeout(() => {
resolve(第三个状态);
}, 1000);
});
//创建一个新Promise实例
let newPromise = Promise.race([p1, p2, p3]);
//输出新Promise实例的状态
newPromise.then((e) => {
console.log(e);
console.log('success');
}).catch((e) => {
console.log(e);
console.log('fail');
}); // 第二个状态,fail
//因为第二个状态对应的Promise实例更快变化状态,所以新Promise实例的状态,改变为第二个状态的Promise实例的状态,并接收第二个状态的reject返回的值。
3.Promise.resolve() :该方法也会返回一个新的Promise,该实例的状态为resolve。
Promise.resolve(100).then((n) => {
console.log(n); // 100
})
4.Promise.reject() :该方法也会返回一个新的Promise,该实例的状态为reject。
Promise.reject(100).catch((n) => {
console.log(n); // 100
})
当Promise对象中的状态被第一个then或catch解析后,后面的then或reject就无法接收到该状态中包含的参数了。
5.Promise.allSettled() (ES11 2020年新增):该方法传入一个Promise对象组成的数组,在该数组的传入的所有Promise对象的状态都凝固后,将结果返回,可以使用.then()方法提取返回的结果,返回的结果是一个数组对象,输出结果的每个数组项与输入的数组项一一对应,数组项第一个属性status标识Promise对象的状态,第二个属性value表示Promise对象返回的结果。