如何在 js 中使用代理使承诺看起来同步?


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每个属性,并处理非功能属性。

相关内容

最新更新