JavaScript 代理在“get”上返回异步值

ech*_*ppy 5 javascript asynchronous es6-proxy

我有一些从网络服务器获取的对象。对象的某些属性需要额外的异步解析,但出于性能原因我想延迟执行此操作。我试图使用代理来拦截访问,然后在访问时解析属性。我的处理程序看起来像这样

class MyClass {
   type() {
      return "my new class";
   }
}

let myObject = new MyClass();

let proxy = new Proxy(myObject, {
  get: async(target, prop, receiver) => {
    if (prop === "attribute") {
      let newProp = prop + "_parsed";
      if (!(newProp in target)) {
        return await (new Promise((resolve, reject) => { resolve("parsed value") }));
      }
      else {
        return target[newProp];
      }
    }
    else {
      return Reflect.get(target, prop, receiver);
    }
  },
});

console.log(proxy.attribute);  // "parsed value"
console.log(proxy.type()); // "my new class"
Run Code Online (Sandbox Code Playgroud)

如果这有效,我希望看到

parsed value
my new class
Run Code Online (Sandbox Code Playgroud)

但我得到以下信息:

{}
{
  "message": "Uncaught TypeError: proxy.type is not a function",
  "filename": "https://stacksnippets.net/js",
  "lineno": 41,
  "colno": 19
}
Run Code Online (Sandbox Code Playgroud)

有什么方法可以通过代理返回异步值,但让调用代码认为它只是访问属性?我什至愿意强制“解析”逻辑(由承诺表示)同步,但是其中有部分是异步的,所以我不确定如何做到这一点。

Ber*_*rgi 5

您不能(不应该)使用async陷阱的方法get。这些总是返回承诺,而您想要.type返回一个函数。你想用

\n
async function parseValue() {\n  await new Promise(resolve => setImmediate(resolve));\n  return "parsed value";\n}\nlet proxy = new Proxy(myObject, {\n  get(target, prop, receiver) {\n    if (prop === "attribute") {\n      let newProp = prop + "_parsed";\n      if (!(newProp in target)) {\n        target[newProp] = parseValue();\n      }\n      return target[newProp];\n    } else {\n      return Reflect.get(target, prop, receiver);\n    }\n  },\n});\n
Run Code Online (Sandbox Code Playgroud)\n
\xe2\x80\xa6\nconsole.log(await proxy.attribute);\nconsole.log(proxy.type());\n
Run Code Online (Sandbox Code Playgroud)\n

  • 您无法使用代理和/或“异步函数”隐藏异步行为。在 javascript 中,您应该拥抱异步,而不是尝试强制同步。`deasync` 确实是一个可怕的黑客,会导致不惯用和 [imo errorprone](/sf/answers/1781310261/) 代码。 (2认同)