[JavaScript理论学习] 什么是Promise (含如何判断一个值是Promise)

发布时间 2023-09-08 01:40:43作者: 叁仟月

什么是Promise (含如何判断一个值是Promise)

本文旨在对 Promise 的规范进行解释, 便于读者在学习 Promise 的过程中梳理 Promise 之间的操作关系, 不对具体的代码实现和Promise用法进行解释.

比如, 为什么 [MDN-await] 中要提及一个 thenable 对象, 而且这个 thenable 对象还可以和 Promise 实例一样使用 await 等待处理, 这就涉及到了下面的内容.

由于笔者编程水平的限制, 不可避免存在错漏或者语意不清的地方.

Promise A+ 规范

参考资料: [Promises/A+]

在 ES6 之前,社区已经有了 Promise A+ 规范, 该规范定义了 Promise 的行为和接口. 根据规范, 任何具有 .then() 方法的函数或对象都可以被认为是一个 Promise ,并且可以进行 Promise 之间的操作。

这个具有 .then() 方法的函数/对象被称为 thenable 对象, 你可以在 [MDN-Promise#thenable][Promises/A+] 查阅到相关资料.

如果读者您熟悉 ES6 中的 Promise , 那么对 Promise A+ 规范一定不陌生, 因为 ES6 中的 Promise 就是基于 Promise A+ 规范的官方实现和拓展. 我们可以将 ES6 的 Promise 称为 Promise 对象, 在 ES6 之前, 第三方库实现的 Promise A+ 规范对象称为 thenable 对象.

该规范旨在于解决回调地狱和异步实现不统一的问题. 早在 ES6 之前, 就有很多第三方库遵守和支持这个规范. 比如 jQuery 中的 $.ajax() / $.get() 等方法返回的就是一个 JQuery 实现的 thenable 对象.

ES6 Promise

基于 Promise A+ 规范, 在 ES6 中新增了一个构造函数 Promise, 通过实例化 Promise (new Promise()) 可以新建一个 Promise 对象, 这个对象是一个符合 Promise A+ 规范的对象 .

如果为了便于理解, 我们可以将 Promise 对象 简单理解为一个继承了 thenable 对象 的对象.

不过在 Promise A+ 的基础上, ES6还拓展了更多的功能, 比如 .catch() 方法, .finally() 方法 , 静态方法 Promise.all() 等等, 具体可以查阅 MDN-Promise .

需要另外了解的一点是, .catch( (error) => {} )方法本质上就是第一个参数传入了空参数的.then( undefined, (error) => {} )方法.

最小实现的 Promise 和最大实现的 Promise

综上所述, 我们可以将 Promise A+ 规范规定的 Promise 称为最小实现的 Promise, 也就是 thenable 对象; 将 ES6 的 Promise 成为最大实现的 Promise, 即 Promise 对象.

如果要检测一个值是否为最小实现的 Promise , 只需要检测是否函数/对象, 并且存在 .then() 方法即可.

如果要检测一个值是否为最大实现的 Promise, 则只需要在上面的检测的基础上, 添加一个 .finally() 方法的检测.

什么是Promise

在 Promise A+ 规范中, Promise 就是一个具有 .then() 方法的函数或者对象.

在 ES6(ES2015) 中, Promise 是一个构造函数, 通过这个构造函数可以实例化一个符合 Promise A+ 规范的对象.

在 ES7(ES2016) 及其之后的版本, 还可以使用 await / async 去调用所有符合 Promise A+ 规范的对象, 包括一些第三方库自己实现的符合 Promise A+ 规范的对象.

只要是符合 Promise A+ 规范的 Promise , 那么它们之间就可以互相操作.

工具函数, 检测一个对象是否为Promise

通常不会直接使用类似value instanceof Promise的判断, 而是给予 Promise A+ / ES6 Promise 规范判断.

最小限定的检测, 检测是否为 thenable 对象.

/**
 * 判断传入参数是否为 Promise (最小实现)
 * @param { any } value
 * @return { boolean } 是否为 Promise
 * @description 代码源于第三方库 is-promise
 * @tutorial https://www.npmjs.com/package/is-promise
 * */
function isPromise( value ) {
	return !!value
		&& (typeof value === 'object' || typeof value === 'function')
		&& typeof value.then === 'function';
}

取消了 typeof value === 'function' 的判断, 因为通过 new Promise() 实例化的值一定是一个对象.

如果想更严格一下, 还可以将 .catch() 方法也加进判断, 也有些工具函数只判断 .then() 方法和 .catch() 方法是否存在, 这只看使用者是想如何限定 Promise 的范围.

/**
 * 判断传入参数是否为 Promise (最大实现)
 * @param { any } value
 * @return { boolean } 是否为 Promise
 * */
function isStrictPromise( value ) {
	return !!value
		&& typeof value === 'object'
		&& typeof value.then === 'function'
		&& typeof value.finally === 'function';
}