技术讲座:Promise 规范中的 ‘Thenable’ 适配:JS 如何兼容所有第三方的 Promise 实现
引言
在 JavaScript 中,Promise 是一个用于异步编程的重要特性。它允许我们以同步代码的方式编写异步代码,从而提高代码的可读性和可维护性。然而,Promise 的实现并非只有一个,不同的库和运行时环境都有自己的 Promise 实现。那么,JavaScript 如何能够兼容这些不同的 Promise 实现,实现所谓的 ‘Thenable’ 适配呢?本文将深入探讨这个问题。
什么是 Promise?
在讨论 ‘Thenable’ 适配之前,我们先来了解一下 Promise 的基本概念。
Promise 是一个对象,它代表了异步操作的最终完成(或失败)。它有三种状态:
- pending:初始状态,既不是成功,也不是失败。
- fulfilled:操作成功完成。
- rejected:操作失败。
Promise 对象提供了一个 .then() 方法,允许我们指定当 Promise 成功或失败时应该调用的回调函数。
‘Thenable’ 的概念
在 Promise 规范中,存在一个概念叫做 ‘Thenable’。一个 ‘Thenable’ 是一个对象,它具有一个 .then() 方法。这个方法接受两个参数:一个用于处理成功的回调函数,另一个用于处理失败的回调函数。
function isThenable(obj) {
return obj && typeof obj.then === 'function';
}
Promise 规范中的 ‘Thenable’ 适配
JavaScript 能够兼容所有第三方的 Promise 实现,主要是因为 Promise 规范中定义了 ‘Thenable’ 的概念,以及 Promise 的 .then() 方法。
Promise 规范的要求
Promise 规范要求:
- 一个 Promise 对象必须有一个
.then()方法。 .then()方法必须返回一个新的 Promise 对象。
这意味着,无论第三方库如何实现 Promise,只要它们遵循这个规范,JavaScript 引擎就能够识别和处理这些 Promise 对象。
实现 ‘Thenable’ 适配
以下是一个简单的实现,演示了如何使一个非 Promise 对象适配 ‘Thenable’ 接口:
function makeThenable(obj) {
return {
then: function(onFulfilled, onRejected) {
// 创建一个新的 Promise 对象
return new Promise(function(resolve, reject) {
// 模拟异步操作
setTimeout(function() {
try {
// 尝试调用 onFulfilled 或 onRejected
if (onFulfilled) {
resolve(onFulfilled(obj));
} else {
reject(new Error('No onFulfilled provided'));
}
} catch (error) {
reject(error);
}
}, 1000);
});
}
};
}
代码示例
以下是一些使用 ‘Thenable’ 适配的代码示例:
PHP 示例
class ThenableExample implements PromisePromiseInterface {
public function then(callable $onFulfilled, callable $onRejected) {
// 模拟异步操作
$this->asyncOperation(function($result) use ($onFulfilled, $onRejected) {
if ($onFulfilled) {
$onFulfilled($result);
} else {
$onRejected(new Exception('No onFulfilled provided'));
}
});
}
private function asyncOperation(callable $callback) {
// 模拟异步操作
$this->doSomething(function() use ($callback) {
$callback('Operation completed');
});
}
private function doSomething(callable $callback) {
// 模拟异步操作
usleep(1000000);
$callback('Async result');
}
}
Python 示例
class ThenableExample:
def then(self, on_fulfilled, on_rejected):
# 模拟异步操作
def async_operation():
try:
result = self.do_something()
on_fulfilled(result)
except Exception as e:
on_rejected(e)
def do_something(self):
# 模拟异步操作
import time
time.sleep(1)
return 'Async result'
# 使用 ThenableExample
example = ThenableExample()
example.then(lambda x: print(x), lambda e: print(e))
Shell 示例
#!/bin/bash
# 定义一个 Thenable 接口的函数
function thenable {
local obj=$1
local onFulfilled=$2
local onRejected=$3
# 模拟异步操作
sleep 1
if [[ -n $onFulfilled ]]; then
onFulfilled "$obj"
else
onRejected "No onFulfilled provided"
fi
}
# 使用 Thenable 接口
thenable "Async result" "Success" "Error"
SQL 示例
-- SQL 中的异步操作通常需要使用外部程序或触发器来实现。
-- 以下是一个简单的 SQL 触发器示例,它模拟了异步操作。
CREATE TRIGGER async_trigger
AFTER INSERT ON some_table
FOR EACH ROW
BEGIN
-- 模拟异步操作
CALL sleep(1);
-- 执行回调函数
IF NEW.onFulfilled IS NOT NULL THEN
SET NEW.result = NEW.onFulfilled(NEW.result);
ELSE
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'No onFulfilled provided';
END IF;
END;
结论
JavaScript 能够兼容所有第三方的 Promise 实现,主要是因为 Promise 规范中定义了 ‘Thenable’ 的概念,以及 Promise 的 .then() 方法。通过实现 ‘Thenable’ 接口,第三方库可以确保它们的 Promise 对象与 JavaScript 引擎兼容。本文通过多个编程语言的示例,展示了如何实现 ‘Thenable’ 适配,并提供了代码示例以供参考。