【问题标题】:Using ES6 Proxy to lazily load resources使用 ES6 Proxy 懒加载资源
【发布时间】:2021-07-04 06:03:21
【问题描述】:

我正在为存储在 MongoDB 中的文档构建类似 ActiveRecord 类的东西(类似于 Mongoose)。我有两个目标:

  1. 使用代理拦截文档上的所有属性设置器,并自动创建要发送到 Mongo 的更新查询。对于这个问题,我已经在 SO 上找到了 a solution

  2. 防止从数据库中进行不必要的读取。 IE。如果在文档上执行了一个函数,并且该函数只设置属性,并且不使用文档的现有属性,那么我不需要从数据库中读取文档,我可以直接更新它。但是,如果函数使用文档的任何属性,我必须先从数据库中读取它,然后才能继续使用代码。示例:

    // Don't load the document yet, wait for a property 'read'.
    const order = new Order({ id: '123abc' });
    // Set property.
    order.destination = 'USA'; 
    // No property 'read', Order class can just directly send a update query to Mongo ({ $set: { destination: 'USA' } }).      
    await order.save();                            
    
    // Don't load the document yet, wait for a property 'read'.
    const order = new Order({ id: '123abc' });
    // Read 'weight' from the order object/document and then set 'shipmentCost'.
    // Now that a 'get' operation is performed, Proxy needs to step in and load the document '123abc' from Mongo.
    // 'weight' will be read from the newly-loaded document.
    order.shipmentCost = order.weight * 4.5;     
    await order.save();     
    

我该怎么做呢?这似乎很简单:在文档对象上设置一个“获取”陷阱。如果它是第一个属性“get”,则从 Mongo 加载文档并缓存它。但是如何将异步操作放入 getter 中?

【问题讨论】:

    标签: javascript node.js mongodb metaprogramming es6-proxy


    【解决方案1】:

    算术不能异步

    您可能可以从 getter 中启动异步读取(我没有尝试过,但它似乎合法),但 getter 不能等待结果。因此,除非您的数据库库提供一些阻塞访问调用,否则order.weight 被及时获取并且乘法中使用的值的这一行在any中将永远是纯粹的幻想em> 惰性读取机制:

    order.shipmentCost = order.weight * 4.5
    

    (如果您的数据库库确实有阻塞读取,我认为只使用阻塞读取来构建您想要的内容会很简单。试试吧。我认为这是 Sequelize 的 dataLoader 所做的一部分.)

    乘法无法对 Promise 进行操作。没有办法等待本身不是异步的异步值。即使是严格来说不是异步/等待的事件,也需要一些异步外观回调模式,它们都不是阻塞的,因此它们都不能使该语句起作用。

    可以工作,但它会强制每个调用者管理延迟加载:

    order.shipmentCost = (await order.weight) * 4.5
    

    这种方法会使您的整个生态系统变形。调用者最好在需要时简单地调用readsave

    或者您可以创建一个在 getter 内部工作的生成器,但您仍然需要为每个属性的首次访问明确地“启动泵”,这将使“幻想”语句以生成为代价工作awaits 的一个可怕的预先声明。同样,最好只使用readsave


    我认为您所希望的在 javascript 中是不可能的,因为阻塞和非阻塞行为是不透明的,也无法做到。任何异步机制最终都会表现为非标量。

    您需要创建自己的预编译器,例如 JSX,它可以将幻想代码转换为异步/感知垃圾。


    严肃的建议:使用现成的持久性库而不是自己开发

    1. 数据持久性的问题空间充满了许多非常困难的问题和边缘情况。你必须解决的问题比你想象的要多。
    2. 除非您的整个项目是“构建更好的持久性技术”,否则您不会构建比现有技术更好的东西,这意味着构建自己的项目只是获得劣质解决方案。
    3. 您编写的代码越多,需要修复的错误就越多。 (而且您正在为这个神奇的持久性库编写测试,对吧?)

    如果您正在尝试构建一个真正的应用程序并且只需要与 Mongo 交互,请花 15 分钟在 npm 上购物并继续前进。人生如此短暂。没有人会关心你的手动数据库层有多“酷”,它几乎类似于 ActiveRecord(除了一些自以为是的自定义错误缺少功能——所有这些都会成为他人甚至你自己的障碍)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-26
      • 1970-01-01
      • 2017-08-29
      • 2016-03-11
      • 2020-06-13
      • 2023-03-24
      相关资源
      最近更新 更多