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对象给链式操作的下一个方法

  1. p1
  2. .then((d) => {
  3. console.log(d); //输出success,p1的状态执行它
  4. return new Promise((resolve, reject) => {
  5. resolve('success123');
  6. });
  7. })
  8. .then((d) => { //success123,这里的参数值是上面的then里面的状态传下来值。
  9. console.log(d);
  10. return new Promise((resolve, reject) => {
  11. resolve('success123456');
  12. });
  13. })
  14. .then((d) => {
  15. console.log(d); //success123456 这里的d必须依靠上面的then里面的状态传下来。
  16. });

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)’),

$ajax(‘http://api.k780.com/?app=phone.get&phone=13800138000&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json‘),

$ajax(‘http://api.k780.com/?app=idcard.get&idcard=110101199001011114&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json‘)

]); //将三个Promise实例作为参数放进这个新Promise实例中。

获取三个接口的值,如果这三个Promise任意一个接口报错都会导致所有接口都无法读取,并报错。

new Promise.then((e) => {

console.log(e);

}).catch((e) => {

console.log(e);

});

2.Promise.race() :这个方法同样是将多个Promise实例,包装成一个新的Promise实例,接受一个数组作为参数,只要其中一个实例率先改变状态,则整个的状态就跟着改变。哪个实例的状态先改变,就跟着该实例改变自身状态。

  1. //创建三个Promise对象
  2. let p1 = new Promise((resolve,reject) => {
  3. setTimeout(() => {
  4. resolve(第一个状态);
  5. }, 2000);
  6. });
  7. let p2 = new Promise((resolve,reject) => {
  8. setTimeout(() => {
  9. reject(第二个状态);
  10. }, 500);
  11. });
  12. let p3 = new Promise((resolve,reject) => {
  13. setTimeout(() => {
  14. resolve(第三个状态);
  15. }, 1000);
  16. });
  17. //创建一个新Promise实例
  18. let newPromise = Promise.race([p1, p2, p3]);
  19. //输出新Promise实例的状态
  20. newPromise.then((e) => {
  21. console.log(e);
  22. console.log('success');
  23. }).catch((e) => {
  24. console.log(e);
  25. console.log('fail');
  26. }); // 第二个状态,fail
  27. //因为第二个状态对应的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对象返回的结果。