我终于弄懂了Promise

2022-12-18 0 920

写在后面

从前常常TNUMBERV12V4,此次总算把它弄了个确切

为的是更快的写作新体验请用提前布局出访

什么是Promise

ES6 触发器程式设计的一种软件系统,比现代的计划(反弹表达式和该事件)更为的科学合理和强悍益处 触发器操作方式以同步操作方式的业务流程唱出来,防止了一层层冗余的反弹表达式promise能化解触发器的问题,这类不能说promise是触发器的

Promise特征

第一类的状况不受韦尔恩。Promise第一类代表者两个触发器操作方式,有四种状况:pending(进行中)、resolved(已获得成功)和rejected(已失利)除非状况发生改变,就不能再变,任何人时候都能获得这个结论。Promise第一类的状况发生改变,只有三种可能:从pending转变成resolved和从pending转变成rejectedpromise外部发生严重错误,不能影响到外部流程的继续执行。难以中止Promise。除非增建它就会立刻继续执行,难以半途中止。其二,如果不增设反弹表达式,Promise外部放出的严重错误,不能化学反应到外部。第二,当处在pending状况时,难以获知目前重大进展到哪两个期(就此结束还是将要顺利完成)

用语

此基础用语

缔造Promise示例时,要传至两个表达式做为模块

new Promise(() => {}); new Promise(); // 收起

该表达式能转交除此之外两个由JavaScript发动机提供更多的表达式,resolve和reject。表达式作用:

resolve——将Promise第一类的状况从pending转变成resolved,将触发器操作方式的结论,做为模块传递进来reject——将Promise第一类的状况从pending转变成rejected,将触发器操作方式算出的错误,做为模块传递进来
let promise = new Promise((resolve, reject) => { // do something if (true) { // 将模块回到,供then方式采用 resolve(“value”); } else { // 将模块回到,供then方式采用 reject(“error”); } }); Promise示例聚合以后,能用then方式依次选定resolved状况和rejected状况的反弹表达式。 promise.then( value => { // resolved时初始化,value为resolve表达式回到的模块 console.log(value); }, err => { // rejected时初始化,err为reject表达式回到的模块 console.log(err); } );

当then方式只有两个表达式模块时,此时为resolved状况的反弹方式

promise.then(value => { // 只有状况为resolved时才能初始化,如果回到的是rejected状况,则收起 Uncaught (in promise) error console.log(value); });

只有当promise的状况转变成resolved或者rejected时,then方式才会被初始化

Promise 增建后就会立刻继续执行,并且初始化resolve或reject后不能终结 Promise的模块表达式的继续执行。

let promise = new Promise(function(resolve) { console.log(“Promise”); resolve(); console.log(“!!!”) }); promise.then(function() { console.log(“resolved.”); }); console.log(“Hi!”); // Promise // !!! // Hi! // resolved resolve回到的是除此之外两个Promise示例 const p1 = new Promise((_, reject) => { setTimeout(() => reject(error), 3000); }); const p2 = new Promise(resolve => { setTimeout(() => resolve(p1), 1000); }); p2.then( result => console.log(result), error => console.log(error) // error );

上面代码中,p1是两个 Promise,3 秒之后转变成rejected。p2的状况在 1 秒之后发生改变,resolve方式回到的是p1。由于p2回到的是另两个 Promise,导致p2自己的状况无效了,由p1的状况决定p2的状态。所以,后面的then语句都变成针对后者(p1)。又过了 2 秒,p1转变成rejected,导致触发catch方式选定的反弹表达式。

以上是原文解释,我们能理解成p2.then 实际上是p1.then

Promise.prototype.then()

then方式是定义在原型第一类Promise.prototype上的,同时then方式的两个模块都是非必选的。因为then方式回到的是两个全新的promise示例时,因此then方式能链式初始化

then方式在以下情况回到的promise

当未传至模块时,then方式会回到两个新的,状况和原promise相同的promise
const promise = new Promise(resolve => { resolve(“resolve”); }); let p = promise.then(); console.log(promise); console.log(p);

结论展示

我终于弄懂了Promise

上两个promise未被获得成功初始化then方式时,回到的结论如情形1
const promise = new Promise((_, reject) => { reject(“reject”); }); let a = promise.then(value => { console.log(value); });
上两个promise被获得成功初始化then方式时,回到两个resolve(undefined)的promise
const promise = new Promise((_, reject) => { reject(“reject”); }); let a = promise.then(undefined, value => { console.log(value); }); console.log(a);
上两个promise被获得成功初始化then方式,但出现收起,回到两个reject(error)的promise,error代指严重错误,并非真正的reject回到的结论
const promise = new Promise(resolve => { resolve(“resolve”); }); let p = promise.then(value => { console.log(value); throw new Error(“fail1”); }); console.log(p);

结论展示:​

我终于弄懂了Promise
给then方式手动回到两个promise,此时会覆盖掉默认的行为,回到值为新增的promise
const promise = new Promise(resolve => { resolve(“resolve”); }); let p = promise.then( () => new Promise(resolve => { resolve(“resolve2”); }) ); console.log(p); Promise.prototype.catch()

catch()方式是.then(null, rejection)或.then(undefined, rejection)的别名,用于选定发生严重错误时的反弹表达式。

const promise = new Promise((_, reject) => { reject(“reject”); }); promise .then(value => { console.log(value); }) // 发生严重错误,或者reject时继续执行 .catch(value => { console.log(value); });

如果 Promise 状况已经变成resolved,再放出严重错误是无效的。

const promise = new Promise(resolve => { resolve(“resolve”); throw new Error(“fail”); }); promise.then(value => console.log(value));

promise中所有没有被处理的严重错误都会冒泡到最后两个catch中

const promise = new Promise(resolve => { resolve(“resolve”); }); promise .then(value => { console.log(value); throw new Error(“fail1”); }) .then(() => { throw new Error(“fail2”); }) .catch(value => { console.log(value); });

在上面的代码中,catch会优先打印打印第两个严重错误,当第两个严重错误化解之后(注释掉就ok),catch里才会打印第二个严重错误

catch的回到值仍是promise,回到promise的方式和then相似,因此,catch后仍然能初始化then方式

Promise.prototype.finally()

finally()方式用于选定不管 Promise 第一类最后状况如何,都会继续执行的操作方式。

finally方式的反弹表达式不接受任何人模块,这表明,finally方式里面的操作方式,应该是与状况无关的,不依赖于 Promise 的继续执行结论。

const promise = new Promise(resolve => { resolve(“resolve”); }); promise.finally(() => { console.log(11); // 11 }); finally的本质 promise.finally(() => { // do something }); // 等同于 promise.then( result => { // do something return result; }, error => { // do something throw error; } );

finally的回到值为两个新的和原来的值相似的promise

Promise.resolve()

有时需要将现有第一类转为 Promise 第一类,Promise.resolve()方式就起到这个作用,且示例状况为resolve

Promise.resolve(foo) // 等价于 new Promise(resolve => resolve(foo))

Promise.resolve()方式的模块分成四种情况

模块是两个 Promise 示例

const promise = new Promise(resolve => { resolve(“resolve”); }); let p = Promise.resolve(promise); console.log(p == promise); // true

模块是两个thenable第一类

thenable第一类指的是具有then方式的第一类,Promise.resolve()方式会将这个第一类转为 Promise 第一类,然后就立刻继续执行thenable第一类的then()方式

// thenable第一类 let thenable = { then: function(resolve, reject) { resolve(42); } }; let p1 = Promise.resolve(thenable); p1.then(function (value) { console.log(value); // 42 });

上面代码中,thenable第一类的then()方式继续执行后,第一类p1的状况就转变成resolved,从而立刻继续执行最后那个then()方式选定的反弹表达式,输出42

模块不是具有then()方式的第一类,或根本就不是第一类

const p = Promise.resolve(Hello); p.then(function (s) { console.log(s) // Hello });

不带有任何人模块

Promise.resolve()方式允许初始化时不带模块,直接回到两个resolved状况的 Promise 第一类

Promise.resolve(); // 相当于 new Promise(resolve => resolve(undefined))

Promise.reject()

Promise.reject(reason)方式也会回到两个新的 Promise 示例,该示例的状况为rejected

const p = Promise.reject(出错了); // 等同于 const p = new Promise((resolve, reject) => reject(出错了))

Promise.all()

Promise.all()方式用于将多个 Promise 示例,包装成两个新的 Promise 示例

const p = Promise.all([p1, p2, p3]);

面代码中,Promise.all()方式接受两个数组做为模块,p1、p2、p3都是 Promise 示例,如果不是,就会初始化Promise.resolve方式,将模块转为 Promise 示例,再进一步处理。除此之外,Promise.all()方式的模块能不是数组,但要具有 Iterator 接口,且回到的每个成员都是 Promise 示例。

p的状况由p1、p2、p3决定,分成三种情况。

只有p1、p2、p3的状况都变成fulfilled,p的状况才会变成fulfilled,此时p1、p2、p3的回到值组成两个数组,传递给p的反弹表达式。只要p1、p2、p3之中有两个被rejected,p的状况就变成rejected,此时第两个被reject的示例的回到值,会传递给p的反弹表达式。
let promise = Promise.all([1, 2, 3]); promise.then(value => { console.log(value); // [1,2,3] }); console.log(promise);

情形一promise结论:​

我终于弄懂了Promise
let p2 = Promise.reject(2); let promise = Promise.all([1, p2, 3]); promise .then(value => { console.log(value); }) .catch(err => { console.log(err); // 2 }); console.log(promise);

情形二promise结论:​

我终于弄懂了Promise

如果做为模块的 Promise 示例,自己定义了catch方式,那么它除非被rejected,并不能触发Promise.all()的catch方式

const p1 = new Promise(resolve => { resolve(“hello”); }) .then(result => result) .catch(e => e); const p2 = new Promise(() => { throw new Error(“收起了”); }) .then(result => result) .catch(e => e); // p2实际上是catch回到的promise示例 Promise.all([p1, p2]) .then(result => console.log(result)) .catch(e => console.log(e)); Promise.race()

Promise.race()方式同样是将多个 Promise 示例,包装成两个新的 Promise 示例。

Promise.race()方式的模块与Promise.all()方式一样,如果不是 Promise 示例,就会先初始化下面讲到的Promise.resolve()方式,将模块转为 Promise 示例,再进一步处理。

const p = Promise.race([p1, p2, p3]);

上面代码中,只要p1、p2、p3之中有两个示例率先发生改变状况,p的状况就跟着发生改变。那个率先发生改变的 Promise 示例的回到值,就传递给p的反弹表达式。

Promise.allSettled()

Promise.allSettled()方式接受一组 Promise 示例做为模块,包装成两个新的 Promise 示例。只有等到所有这些模块示例都回到结论,不管是fulfilled还是rejected,包装示例才会结束,模块与Promise.all()方式一样

let p2 = Promise.reject(2); let promise = Promise.allSettled([1, p2, 3]); promise.then(value => { console.log(value); // [{status: “fulfilled”, value: 1},{status: “rejected”, reason: 2},{status: “fulfilled”, value: 3}] }); console.log(promise);

Promise.allSettled()的回到的promise示例状况只可能变成resolved,它的监听表达式收到的模块是两个数组,该数组的每个成员都是两个第一类,每两个第一类都有status属性,该属性的值只可能是字符串fulfilled或字符串rejected。fulfilled时,第一类有value属性,rejected时有reason属性,对应三种状况的回到值。

Promise.any()

该方式接受一组 Promise 示例做为模块,包装成两个新的 Promise 示例回到。只要模块示例有两个变成fulfilled状况,包装示例就会变成fulfilled状况;如果所有模块示例都变成rejected状况,包装示例就会变成rejected状况。

Promise.any()跟Promise.race()方式很像,只有一点不同,就是不能因为某个 Promise 变成rejected状况而结束。

let p1 = Promise.reject(1); let p2 = Promise.reject(2); let promise = Promise.any([p1, p2, 3]); promise.then(value => { console.log(value); // 3 }); console.log(promise);

当所有的示例回到的状况都是rejected时,Promise.any()会回到两个的示例状况才为rejected

let p1 = Promise.reject(1); let p2 = Promise.reject(2); let promise = Promise.any([p1, p2]); promise .then(value => { console.log(value); }) .catch(value => { console.log(value); // AggregateError: All promises were rejected }); console.log(promise);

Promise.try()

实际开发中,经常遇到一种情况:不知道或者不想区分,表达式f是同步表达式还是触发器操作方式,但是想用 Promise 来处理它。因为这样就能不管f是否包含触发器操作方式,都用then方式选定下一步流程,用catch方式处理f放出的严重错误。一般就会采用下面的写法。

const f = () => console.log(now); Promise.resolve().then(f); console.log(next); // next // now

上面的写法有两个缺点,就是如果f是同步表达式,那么它会在本轮该事件循环的末尾继续执行。

鉴于这是两个很常见的需求,所以现在有两个提案,提供更多Promise.try方式替代上面的写法。

const f = () => console.log(now); Promise.try(f); console.log(next); // now // next

参考

https://es6.ruanyifeng.com/#docs/promise

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务