[JavaScript理论学习] 什么是Promise (含如何判断一个值是Promise)
什么是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';
}