0

次のように、のIDを提供するときに特定のAPIメソッドを呼び出すことができるAPIクライアントに取り組んでいますfoo:

apiClient.myApiMethod('myFooId', 'firstApiArg', 'nthApiArg');

開発者の利便性のために、カスタム プロキシ オブジェクトを実装しようとしています。

var myFoo = apiClient.registerFoo('myFoo', 'myFooId');
myFoo.myApiMethod('firstApiArg', 'nthApiArg');

しばらく検索した後、fooId両方の作業方法をサポートするためにメソッド呼び出しの最初の引数として挿入する必要があるため、ES6 プロキシが最適であると考えました。
そのため、次のコードを作成しました。のオブジェクト プロパティFoo.myFoosが呼び出されると (例: Foo.myFoos.example)、そのプロパティが で検索され_myFooItems、存在する場合は別の Proxy オブジェクトが返されます。その
オブジェクトで メソッドが呼び出されると、 のプロパティで検索され、見つかった場合は、メソッドが最初の引数として呼び出されます。 つまり、できるはずです。FooFoomyFooId
Foo.myFoos.example.parentMethodX('bar', 'baz')

var Foo = function() {

  // parent instance
  _self = this;

  // custom elements dictionary
  _myFooItems = {};

  // to call parent methods directly on custom elements
  this.myFoos = Object.create(new Proxy({}, {

      // property getter function (proxy target and called property name as params)
      get: function(target, myFooName) {

        // whether called property is a registered foo
        if (_myFooItems.hasOwnProperty(myFooName)) {

          // create another proxy to intercept method calls on previous one
          return Object.create(new Proxy({}, {

              // property getter function (proxy target and called property name as params)
              get: function(target, methodName) {

                // whether parent method exists
                if (_self.hasOwnProperty(methodName)) {

                  return function(/* arguments */) {

                    // insert custom element ID into args array
                    var args = Array.prototype.slice.call(arguments);
                    args.unshift(_myFooItems[ myFooName ]);

                    // apply parent method with modified args array
                    return _self[ methodName ].apply(_self, args);
                  };
                } else {

                  // parent method does not exist
                  return function() {
                    throw new Error('The method ' + methodName + ' is not implemented.');
                  }
                }
              }
            }
          ));
        }
      }
    }
  ));


  // register a custom foo and its ID
  this.registerFoo = function(myFooName, id) {

    // whether the foo has already been registered
    if (_myFooItems.hasOwnProperty(myFooName)) {
      throw new Error('The Foo ' + myFooName + ' is already registered in this instance.');
    }

    // register the foo
    _myFooItems[ myFooName ] = id;

    // return the created foo for further use
    return this.myFoos[ myFooName ];
  };
};

module.exports = Foo;

コードを実行して登録しようとするとfoo(上記のコードは Node>=6.2.0 でそのまま動作します)、次のエラーがスローされます。

> var exampleFoo = Foo.registerFoo('exampleFoo', 123456)
Error: The method inspect is not implemented.
  at null.<anonymous> (/path/to/module/nestedProxyTest.js:40:31)
  at formatValue (util.js:297:21)
  at Object.inspect (util.js:147:10)
  at REPLServer.self.writer (repl.js:366:19)
  at finish (repl.js:487:38)
  at REPLServer.defaultEval (repl.js:293:5)
  at bound (domain.js:280:14)
  at REPLServer.runBound [as eval] (domain.js:293:12)
  at REPLServer.<anonymous> (repl.js:441:10)
  at emitOne (events.js:101:20)

メソッドが指定されていないのに、なぜ 2 番目のプロキシがメソッドを呼び出そうとするのかを考えるのに多くの時間を費やした後、私は最終的にあきらめました。呼び出された場合にメソッドexampleFooを受け入れる Proxy オブジェクトになることを期待しています。 ここでの実際の動作の原因は何ですか?Foo

4

2 に答える 2