本文根据promise英文规范以及ES6源码 总结。本文拙见,欢迎斧正。
这两天学习了一下 nodejs.
看到异步这一块时,百度以下Promise
,发现多篇一律如下图:
![](https://img.haomeiwen.com/i2906649/b965e458c2e7fe25.png)
![](https://img.haomeiwen.com/i2906649/c5d6d1f75945c66f.png)
单线程或者多线程,跟异步没有必然的因果关系。网络和文件读写这种耗时操作才跟异步有关。多线程用来提高系统资源的利用率,异步来解决耗时任务,二者天生就没有必然的因果关。即使JS支持多线程,你也需要异步执行耗时操作,因为多线程的行为表现为异步的,你不知道这个线程啥时候执行完。
看到这两句话:
JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。
由于这个“缺陷”,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行。
就没有再读下去的心思了,多线程只是异步操作的的一种体现方式。所以不能说单线程缺陷
导致必须使用异步。
使用异步完全是因为操作耗时,会造成界面卡顿、无响应等
。
还是promise英文规范最靠谱。
IDE:WebStorm
ES6
前言
promise是一个健全的,可互操作的开放标准,由实现者为实现者。
promise
表示异步操作的最终结果。与promise
交互的主要方式是通过其then
方法,该方法注册回调函数
以接收的promise
的最终值或promise
无法实现的原因。
该规范详细描述了then
方法的行为,提供了一个可交互的基础,所有承诺/A+符合承诺的实现都可以依赖于此基础来提供。因此,应该认为该规范非常稳定。虽然promise /A+
组织可能偶尔会修改这个规范,对它进行一些向后兼容的小修改,以解决新发现的问题,但是我们只有在仔细考虑、讨论和测试之后,才会集成大型的或向后不兼容的修改。
历史上,promise /A+
澄清了较早的promise /A
提案中的行为条款,将其扩展到涵盖实际行为,并省略了未指定或有问题的部分。
最后,核心promise /A+
规范不处理如何创建、实现或拒绝承诺,而是选择专注于提供一个互操作的 then
方法。未来在配套规范中的工作可能会涉及这些主题。
术语
-
promise
:是一个带有then
方法的对象或者一个函数,其行为遵循promise /A+
规范。 -
thenable
:是一个对象或者一个函数,定义then
方法。 -
value
:一个合法的js
类型的值,如undefined, a thenable, or a promise
。 -
exception
:异常。 -
reason
:绝句执行的原因。
三种状态
-
pending
:可能转变完成或者拒绝。 -
fulfilled
:不能转变为其他状态,只能是一个不能改变的value
。 -
rejected
:不能转变为其他状态,只能是一个不能改变的reason
。
在这里,不能改变意味着不变的身份(即===),但并不意味着深度不变。
then方法
定义回调函数,用来接收异步任务的结果。
源码:
interface PromiseLike<T> {
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) =>
TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?:
((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null):
PromiseLike<TResult1 | TResult2>;
}
一个promise
必须提供一个then方法来访问它当前或最终的值或原因。promise的then方法接受两个参数:
promise.then(onFulfilled, onRejected)
参数含义
-
onFulfilled
成功的回调,可选参数。 - 如果不是函数,则被忽略。
- 如果是个函数,则在
promise
执行成功后
被回调,promise’s
的value
会作为第一个参数传递,其实就是resolve();
的一个实现方法。
-
onRejected
失败的回调,可选参数,如果不是函数,则被忽略。 - 如果是个函数,则在
promise
拒绝执行后
被回调,promise’s
的reason
会作为第一个参数传递,其实就是reject();
的一个实现方法。。
如果要回调,这两个参数必须是一个函数:
new Promise.then(function () {
},function () {
});
回调时机
onFulfilled
和 onRejected
只有在执行环境堆栈仅包含平台代码时才可被调用!说白了,就是通过resolve
或者reject``,来执行回调逻辑。
正常业务逻辑下需要调用resolve("参数");
方法去触发回调函数onFulfilled的执行;异常逻辑需要throw
一个异常Error或者通过reject();
方法来触发onRejected的执行。否则不执行回调!
then
一定返回一个promise
实现链式调用的基础
promise2 = promise1.then(onFulfilled, onRejected);
简单的案例
then源码声明:
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) =>
TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?:
((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null):
Promise<TResult1 | TResult2>;
catch 源码(声明):
/**
* Attaches a callback for only the rejection of the Promise.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of the callback.
*/
catch<TResult = never>(onrejected?: ((reason: any) =>
TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
没有出现错误或异常的代码
function promise() {
let promise = new Promise(function (resolve, reject) {
console.log("处理具体业务");
resolve("参数");//
}).then(function (value) {
console.log("处理成功 " + value);
}, function () {
console.log("处理失败");
}).catch(function () {
console.log("处理异常");
});
}
promise();
![](https://img.haomeiwen.com/i2906649/e66cfe2641eb7b94.png)
出现错误或异常的代码
function promise() {
let promise = new Promise(function (resolve, reject) {
try {
console.log("处理具体业务");
ass();//未定义函数
console.log("处理具体业务,异常代码之后");
resolve("参数");//
} catch (e) {
throw new Error("dddd");
// reject();
}
}).then(function (value) {
console.log("处理成功 " + value);
}, function () {
console.log("处理失败");
}).catch(function () {
console.log("处理异常");
});
}
promise();
程序调用了一个未定义的函数ass();
,然后,走catch{}
块,在这个捕获异常的代码块里面,执行reject();
或者抛出一个错误,如果then方法的第二个参数是函数,则会走这个回调函数,如果没有定义第二个回调函数而是定义了一个catch代码块
,则会走catch代码块
,如果即定义了回调函数,又调用了异常处理函数catch代码块
,则只会有回调函数
,如果二者都没有,则程序会报错,以下是未实现回调函数而调用了异常处理函数。
本质上,是有调用了只有声明而没有实现的函数。
1、异常没有被开发者实现:
![](https://img.haomeiwen.com/i2906649/bef268ed8bea4b36.png)
2、reject();
没有被开发者实现:
![](https://img.haomeiwen.com/i2906649/76a474993befdbad.png)
总之,至少要有一个能够异常或者的回调逻辑。
可以被回调多次的then
function doing(value) {
return new Promise(function (resolve, reject) {
try {
console.log(value);
resolve(value);//
// resolve();//
} catch (e) {
// throw new Error("dddd");
reject(value);
}
});
}
function do_something_wrong(value) {
return new Promise(function (resolve, reject) {
try {
console.log(value + "级业务");
// ass();
// reject("业务逻辑异常");
resolve(value);//
// resolve();//
} catch (e) {
// throw new Error("dddd");
reject(value);
}
});
}
function promise() {
let promise = new Promise(function (resolve, reject) {
try {
console.log("一级业务");
ass();
console.log("处理具体业务,异常代码之后");
resolve(1);//
} catch (e) {
// throw new Error("dddd");
reject(2);
}
}).then(function (value) {
doing("二级业务");
}, function (error) {
do_something_wrong("二级业务----处理一级异常");
}).then(function (value) {
doing("三级业务");
}, function (value) {
do_something_wrong("三级业务----处理一级异常");
}).then(function (value) {
doing("四级业务");
}, function (value) {
do_something_wrong("四级业务----处理一级异常");
}).then(function (value) {
doing("五级业务");
}, function (value) {
do_something_wrong("五级业务----处理一级异常");
}).then(function (value) {
doing("六级业务");
}, function (value) {
do_something_wrong("六级业务----处理一级异常");
});
return promise;
}
promise();
![](https://img.haomeiwen.com/i2906649/029ecb7895090d83.png)
英文原文说:
If/when promise is fulfilled, all respective onFulfilled callbacks must execute in the order of their originating calls to then.
If/when promise is rejected, all respective onRejected callbacks must execute in the order of their originating calls to then.
- 当
promise
成功执行时,所有onFulfilled
需按照其链式调用的顺序依次回调。 - 当
promise
被拒绝执行时,所有的onRejected
需按照其链式调用的顺序依次回调。
网友评论