解析 Promise 规范中的 ‘Thenable’ 适配:为什么 JS 能够兼容所有第三方的 Promise 实现?

技术讲座: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 规范要求:

  1. 一个 Promise 对象必须有一个 .then() 方法。
  2. .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’ 适配,并提供了代码示例以供参考。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注