通过承诺返回 ES6 代理时堆栈溢出
stack overflow when returning an ES6 proxy through a promise
我正在尝试拦截 ES6 代理上的方法调用,以便能够在我从代理获得的信息之间做一些事情。现在,在我的例子中,在从某种工厂创建和 returning 代理之前还有很多事情要做。由于所有这些东西,我决定将先决条件包装到一个 promise 函数中,这样我就可以将代理创建链接到它上面,并 return 通过 promise 链生成代理。这是重现问题的代码:
proxy_factory.min.js
'use strict';
// require('harmony-reflect');
class ProxyFactory {
create(options) {
const self = this;
const handler = {
get(target, propertyKey, receiver) {
if (propertyKey === 'then') {
return function proxyPromiseWrapper(thenCallback) {
const innerProxy = self.create(options);
return thenCallback(innerProxy);
};
}
return function resourceFunctionProxy() {
const callContext = {
target: target,
method: propertyKey,
args: arguments,
thisContext: this
};
const resourceInstanceMethod = Reflect.get(options.originalObject, callContext.method);
return resourceInstanceMethod.apply(callContext.thisContext, callContext.arguments);
};
}
};
return new Proxy(options.originalObject, handler);
}
}
module.exports = ProxyFactory;
test.js
'use strict';
const Promise = require('bluebird');
const ProxyFactory = require('./proxy_factory.min.js');
const proxyFactory = new ProxyFactory();
function createProxyWithPromise() {
const TestClass = class {
doSomething() {
return Promise.resolve('promise return value');
}
};
const options = {
originalObject: new TestClass()
};
return Promise.resolve()
.then(() => {
return proxyFactory.create(options);
});
}
function test() {
createProxyWithPromise()
.then((proxy) => {
const result = proxy.doSomething();
console.log(result); // should output 'promisereturnvalue'
});
}
test();
在代理上调用 doSomething() 之前,then() 函数被一遍又一遍地调用,导致堆栈溢出。
我已经在 node.js github 问题中问过这个问题,你可以在这里找到之前的对话:https://github.com/nodejs/node/issues/8082
也许它可以帮助帮助我的人 ;)
这是一个晴天霹雳,但您可能正在寻找
return function proxyPromiseWrapper(thenCallback) {
return options.originalObject.then(function(result) {
const resultOptions = Object.assign({}, options, {target: result});
const innerProxy = self.create(resultOptions);
return thenCallback(innerProxy);
});
};
您的问题是您的代理总是 returns 访问任何 属性 的函数,包括 then
。这将使 promises 实现将它视为一个 thenable,试图解决它——你的代码在那里出现了可怕的错误。但是你应该解决问题的根源:
get (target, propertyKey, receiver) {
if (!(propertyKey in target))
return undefined;
else if (typeof target[propertyKey] != "function")
return …;
else
return function resourceFunctionProxy() {
…
我正在尝试拦截 ES6 代理上的方法调用,以便能够在我从代理获得的信息之间做一些事情。现在,在我的例子中,在从某种工厂创建和 returning 代理之前还有很多事情要做。由于所有这些东西,我决定将先决条件包装到一个 promise 函数中,这样我就可以将代理创建链接到它上面,并 return 通过 promise 链生成代理。这是重现问题的代码:
proxy_factory.min.js
'use strict';
// require('harmony-reflect');
class ProxyFactory {
create(options) {
const self = this;
const handler = {
get(target, propertyKey, receiver) {
if (propertyKey === 'then') {
return function proxyPromiseWrapper(thenCallback) {
const innerProxy = self.create(options);
return thenCallback(innerProxy);
};
}
return function resourceFunctionProxy() {
const callContext = {
target: target,
method: propertyKey,
args: arguments,
thisContext: this
};
const resourceInstanceMethod = Reflect.get(options.originalObject, callContext.method);
return resourceInstanceMethod.apply(callContext.thisContext, callContext.arguments);
};
}
};
return new Proxy(options.originalObject, handler);
}
}
module.exports = ProxyFactory;
test.js
'use strict';
const Promise = require('bluebird');
const ProxyFactory = require('./proxy_factory.min.js');
const proxyFactory = new ProxyFactory();
function createProxyWithPromise() {
const TestClass = class {
doSomething() {
return Promise.resolve('promise return value');
}
};
const options = {
originalObject: new TestClass()
};
return Promise.resolve()
.then(() => {
return proxyFactory.create(options);
});
}
function test() {
createProxyWithPromise()
.then((proxy) => {
const result = proxy.doSomething();
console.log(result); // should output 'promisereturnvalue'
});
}
test();
在代理上调用 doSomething() 之前,then() 函数被一遍又一遍地调用,导致堆栈溢出。 我已经在 node.js github 问题中问过这个问题,你可以在这里找到之前的对话:https://github.com/nodejs/node/issues/8082 也许它可以帮助帮助我的人 ;)
这是一个晴天霹雳,但您可能正在寻找
return function proxyPromiseWrapper(thenCallback) {
return options.originalObject.then(function(result) {
const resultOptions = Object.assign({}, options, {target: result});
const innerProxy = self.create(resultOptions);
return thenCallback(innerProxy);
});
};
您的问题是您的代理总是 returns 访问任何 属性 的函数,包括 then
。这将使 promises 实现将它视为一个 thenable,试图解决它——你的代码在那里出现了可怕的错误。但是你应该解决问题的根源:
get (target, propertyKey, receiver) {
if (!(propertyKey in target))
return undefined;
else if (typeof target[propertyKey] != "function")
return …;
else
return function resourceFunctionProxy() {
…