写在后面
从前常常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相同的promiseconst promise = new Promise(resolve => {
resolve(“resolve”);
});
let p = promise.then();
console.log(promise);
console.log(p);
结论展示
上两个promise未被获得成功初始化then方式时,回到的结论如情形1const promise = new Promise((_, reject) => {
reject(“reject”);
});
let a = promise.then(value => {
console.log(value);
});
上两个promise被获得成功初始化then方式时,回到两个resolve(undefined)的promiseconst 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);
结论展示:
给then方式手动回到两个promise,此时会覆盖掉默认的行为,回到值为新增的promiseconst 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结论:
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 示例,自己定义了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