【问题标题】:Is there a way to recursively await a value in Javascript?有没有办法递归地等待 Javascript 中的值?
【发布时间】:2020-05-28 05:06:26
【问题描述】:

我正在使用 Javascript 制作一个项目,并且我有一个对象,该对象具有一个返回承诺的 getter。我可以用这段代码模拟这个对象:

async function asyncifiedObject(object) {
  let o = {};

  let keys = [...Object.keys(object)];
  for (let item of keys) {
    o.__defineGetter__(item, async () => {
      if (object && object[item]) {
        if (typeof object[item] == "object") {
          // Do other async things, like network requests, etc.
          return await asyncifiedObject(object[item]);
        } else {
          return object[item];
        }
      }
    });
  }
  return o;
}

我得到这样的对象之一:

let o=asyncifiedObject({hello:{world:{it:{is:{nice:{out:"today"}}}}}})

当我访问对象的属性时,我目前正在做await (await (await (await (await (await (await o).hello).world).it).is).nice).out,但这很长而且看起来很糟糕。

我可以使用像await getAsyncValues(o,"hello","world","it","is","nice","out") 这样的函数来完成它,但我想做的是像await o.hello.world.it.is.nice.out 这样的函数,这不起作用,因为所有的承诺都需要等待,而不仅仅是第一个.有什么办法可以吗?

顺便说一下,这是getAsyncValues的示例实现:

async function getAsyncValues(object,...values){
  let r=object;
  for(let value of values){
    r=(await r)[value]
  }
  return r
}

【问题讨论】:

  • __defineGetter__,真的吗?此外,在 Object.keys 周围使用扩展语法也没有意义。
  • "我有一个对象,它有一个返回承诺的 getter" - 既然你说 asyncifiedObject 只是一个模拟,那么你的真实对象是什么样的?
  • 传播语法是我实际实现中需要的东西,我懒得删除,我的真实对象要么从底层对象获取数据,要么从另一台服务器获取数据,因此我需要完全做到这一点。另外,__defineGetter__ 有什么问题?
  • asyncifiedObject 确实与我的真实对象具有相同的语义。
  • __defineGetter__ 自古以来就被弃用了。请改用Object.defineProprty

标签: javascript asynchronous async-await es6-promise


【解决方案1】:

这是一个有趣的情况。不,这里没有任何语法可以帮助您,您需要使用您的函数或类似函数。

【讨论】:

    【解决方案2】:

    我想出了一种方法来让这项工作完全按照我想要的方式进行! await 语句不仅仅适用于 Promise。它也适用于thenables。 thenable 是一个具有类似 Promise 的 then 方法的对象。我修改了getAsyncValues,最终代码如下。

    (async () => {
      async function asyncifiedObject(object) {
        let o = {};
    
        let keys = [...Object.keys(object)];
        for (let item of keys) {
          o.__defineGetter__(item, async () => {
            if (object && object[item]) {
              if (typeof object[item] == "object") {
                // Do other async things, like network requests, etc.
                return thenableHack(await asyncifiedObject(object[item]));
              } else {
                return object[item];
              }
            }
          });
        }
        return o;
      }
    
      function thenableHack(object, ...values) {
        let o = {
          then: async e => {
            let r = object;
            for (let value of values) {
              r = (await r)[value];
            }
            e(r);
          },
          catch: () => {}
        };
        return new Proxy(o, {
          get: (o, p) => {
            return o[p] || thenableHack(object, ...values, p);
          }
        });
      }
    
      let o = thenableHack(
        asyncifiedObject({
          hello: { world: { it: { is: { nice: { out: "today" } } } } }
        })
      );
      console.log(await o.hello.world.it.is.nice.out);
    })();

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-19
      • 1970-01-01
      • 2020-10-22
      • 2019-07-04
      • 2019-09-10
      • 1970-01-01
      相关资源
      最近更新 更多