JavaScript/Proxy/revocable

カテゴリ:Book:JavaScript#Proxy/revocable%20

Proxy.revocable() は、後で無効化(リボーク)できるプロキシを作成するメソッドです。このメソッドは、プロキシオブジェクトとそのプロキシを無効化するための revoke 関数を含むオブジェクトを返します[1]

構文

Proxy.revocable(target, handler)
  • target: プロキシが仮想化するターゲットオブジェクト。
  • handler: トラップを含むオブジェクト。

基本的な使用例

以下のプログラムは、Proxy.revocable() を使用して取り消し可能なプロキシを作成する基本的な例です。

const target = { message: 'hello' };
const handler = {
  get(target, prop, receiver) {
    console.log(`プロパティ "${prop}" へのアクセスが検出されました`);
    return Reflect.get(target, prop, receiver);
  }
};

// 取り消し可能なプロキシを作成
const { proxy, revoke } = Proxy.revocable(target, handler);

// プロキシを使用
console.log(proxy.message); // プロパティ "message" へのアクセスが検出されました、hello

// プロキシを無効化
revoke();

// 無効化後のプロキシへのアクセスは例外をスローする
// console.log(proxy.message); // TypeError: Cannot perform 'get' on a proxy that has been revoked

このプログラムでは、Proxy.revocable() を使用して取り消し可能なプロキシを作成し、revoke 関数を呼び出してプロキシを無効化しています。無効化後にプロキシにアクセスしようとすると、TypeError が発生します。

一時的なアクセス権の例

以下のプログラムは、Proxy.revocable() を使用して一時的なアクセス権を実装する例です。

// センシティブなデータを含むオブジェクト
const sensitiveData = {
  username: 'admin',
  password: 'supersecret',
  apiKey: '1234567890abcdef'
};

// 一時的なアクセス権を付与する関数
function createTemporaryAccess(data, validTimeInMs) {
  const { proxy, revoke } = Proxy.revocable(data, {});
  
  // 指定した時間後にアクセスを取り消す
  setTimeout(revoke, validTimeInMs);
  
  return proxy;
}

// 5秒間だけアクセス可能なプロキシを作成
const temporaryAccess = createTemporaryAccess(sensitiveData, 5000);

// 即座にアクセス可能
console.log(temporaryAccess.username); // "admin"
console.log(temporaryAccess.apiKey); // "1234567890abcdef"

// 5秒後にアクセスを試みる
setTimeout(() => {
  try {
    console.log(temporaryAccess.username);
  } catch (e) {
    console.log('アクセスが取り消されました:', e.message);
    // アクセスが取り消されました: Cannot perform 'get' on a proxy that has been revoked
  }
}, 6000);

このプログラムでは、Proxy.revocable() を使用して、指定した時間(この場合は5秒)だけ有効なデータへのアクセスを提供しています。時間が経過すると、プロキシは自動的に無効化されます。

APIクライアントの例

以下のプログラムは、Proxy.revocable() を使用してAPIクライアントのセッション管理を実装する例です。

// APIクライアントのモック
const apiClient = {
  fetchData() {
    return { status: 'success', data: [1, 2, 3] };
  },
  updateData(data) {
    console.log('データを更新しました:', data);
    return { status: 'success' };
  }
};

// セッション管理機能を持つAPIクライアントを作成
function createSessionClient() {
  let isActive = true;
  
  const { proxy, revoke } = Proxy.revocable(apiClient, {
    get(target, prop, receiver) {
      if (!isActive) {
        throw new Error('セッションが終了しています');
      }
      
      const value = Reflect.get(target, prop, receiver);
      
      // メソッドの場合は、セッションチェックを含むラッパー関数を返す
      if (typeof value === 'function') {
        return function(...args) {
          if (!isActive) {
            throw new Error('セッションが終了しています');
          }
          return value.apply(this, args);
        };
      }
      
      return value;
    }
  });
  
  // セッションを終了する関数
  function endSession() {
    isActive = false;
    revoke();
  }
  
  return { client: proxy, endSession };
}

// セッションクライアントを作成
const { client, endSession } = createSessionClient();

// 通常の操作
console.log(client.fetchData()); // { status: 'success', data: [1, 2, 3] }
client.updateData([4, 5, 6]); // データを更新しました: [4, 5, 6]

// セッションを終了
endSession();

// セッション終了後の操作
try {
  client.fetchData();
} catch (e) {
  console.log('エラー:', e.message); // エラー: Cannot perform 'get' on a proxy that has been revoked
}

このプログラムでは、Proxy.revocable() を使用してセッション管理機能を持つAPIクライアントを実装しています。セッションが終了すると、クライアントのメソッドにアクセスできなくなります。

注意点

  • 非可逆的: プロキシを一度無効化すると、それを元に戻すことはできません。新しいプロキシを作成する必要があります。
  • 参照の保持: revoke 関数への参照を保持していない場合、プロキシを無効化することができなくなります。
  • ガベージコレクション: プロキシを無効化すると、関連するリソースがガベージコレクションの対象になります。
  • エラーハンドリング: 無効化されたプロキシへのアクセスは TypeError をスローするため、適切なエラーハンドリングが必要です。
  • ES2015+: Proxy.revocable() は ECMAScript 2015 (ES6) で導入されました。

脚註

  1. これは、一時的なアクセス権を付与し、後でそのアクセスを取り消す必要がある場合に特に有用です。

外部リンク

カテゴリ:Book:JavaScript#Proxy/revocable%20 カテゴリ:JavaScript
カテゴリ:Book:JavaScript カテゴリ:JavaScript カテゴリ:Pages using the JsonConfig extension