const handler: ProxyHandler<any> = {
get: (target: Promise<any>, prop: string, receiver: any) => {
return target.then((o) => {
return o[prop].apply(o);
});
},
};
return new Proxy(obj, handler);
所以我有这个代码,我从互联网上的要点中复制了它,它似乎有效。我了解陷阱的工作原理,但我不明白代理如何使承诺的返回像同步值一样。我的同事担心这段代码有竞争条件。是否有任何竞争条件?引擎盖下到底发生了什么?我是否需要改进此代码以使其安全?
代码是用打字稿编写的,在 NodeJS 10 上运行。
看起来这段代码根本没有使访问同步。看起来它用于使承诺有效负载上的任何方法在承诺上可用,但它们在调用时仍将延迟执行。
例如,给定以下 API:
interface Bird {
speak(): void;
}
function getBird(): Promise<Bird> {
return new Promise((resolve) => {
setTimeout(() => resolve({ speak() { console.log('CAW'); } }, 1000);
});
}
function proxyPromise<T>(promise: Promise<T>) {
// Your promise proxying code here
}
proxyPromise 代码将允许您在代理对象上调用方法,并推迟它们,直到解决承诺:
const proxiedBird = proxyPromise(getBird());
console.log("Fetching Bird")
proxiedBird.speak;
console.log("Told it to speak");
此代码可以正常执行,但它不会使speak()
操作同步运行 - 它仍将等待getBird()
承诺解析。所以在输出中你会看到:
Fetching Bird
Told it to Speak
CAW
您拥有的代码片段不会支持在代理对象上具有参数的字段或方法。
你可以用一些打字稿来描述它的安全行为:
type MethodProxy<T> = {
[idx in keyof T]: T[idx] extends () => infer U ? Promise<U> : never;
}
function proxyPromise<T>(promise: Promise<T>): MethodProxy<T> {
const handler: ProxyHandler<any> = {
get: (target: Promise<any>, prop: string, receiver: any) => {
return target.then((o) => {
return o[prop].apply(o);
});
},
};
return new Proxy(promise, handler);
}
棘手的问题@xenoterracide。但是回答你,实际上,这根本不同步工作,基本上,你把每个obj
属性都变成了只能异步访问,如果该属性不是函数,它会抛出错误。
在后台,您只是捕获一个承诺get
属性,而在陷阱中,等待承诺解析并执行由承诺解析的此值中的属性(函数(。
我在这个操场上模拟它:
const handler: ProxyHandler<any> = {
get: (target: Promise<any>, prop: string, receiver: any) => {
return target.then((o) => {
return o[prop].apply(o);
});
},
};
const obj = {
a() {
return 'Hi'
},
b: 5
}
const proxy = new Proxy(Promise.resolve(obj), handler);
//both prints promises
console.log(proxy.a) // after resolved, return 'Hi'
console.log(proxy.b) // error
如果您不想解析承诺本身,则此代理方法可能很有用。但是您需要await
每个属性,并处理非功能属性。