【问题标题】:Node.js cache request data from method inside class objectNode.js 缓存来自类对象内部方法的请求数据
【发布时间】:2023-04-09 14:27:01
【问题描述】:

我正在尝试通过在实例化类时调用方法来缓存从 Node.js 中的类中的 get 请求接收到的数据。我只想在创建类的新实例时运行一次。

class GetSomeData {

    constructor() {
        this.storedData = '';
        this.getData();
    }

    getData = async () => {
        const allData = await axios.get(`URL`, config)
        this.storedData = allData
    }
}

let newInstance = new GetSomeData();

当我记录 newInstance.storedData 我得到''。 我正在从 get 请求接收数据,但无法将其存储在 this.storedData 中。

由于某种原因,这可行:

class GetSomeData {

    constructor() {
        this.storedData = this.getData();
    }

    getData = async () => {
        const allData = await axios.get(`URL`, config)
        return allData 
    }
}

let newInstance = new GetSomeData();

当我记录 newInstance.storedData 时,我得到了实际数据。

第二种方法应该在我每次访问 newInstance.storedData 时运行 getData 方法,但实际上它只在创建新实例时运行一次。 我不明白我错过了什么。

【问题讨论】:

    标签: javascript node.js class methods constructor


    【解决方案1】:

    这取决于您拨打console.log的地点/时间。

    请记住,JavaScript 代码执行永远不会停止,并且它仍然是单线程和同步的。异步行为是通过在与外部 I/O 接口(通常来自底层操作系统)交互时排队和处理任务来实现的。

    还请记住,一旦到达第一个 await 语句,async 函数总是隐式返回一个承诺。然后代码在async 函数之外继续执行,直到实现了等待的承诺。

    在第一种情况下,您使用空字符串初始化 storedData 属性,这就是您在异步请求结束之前尝试记录它时得到的结果。

    在第二种情况下,您实际上是在记录一个承诺,然后将使用获取的数据解决该承诺,这就是您看到数据的原因。

    const get = async () => {
      return await new Promise((resolve) => {
        setTimeout(() => {
          resolve('DATA');
        }, 3000);
      });
    };
    
    class GetSomeData {
        constructor() {
            this.storedDataA = '';
            this.storedDataB = this.getData();
        }
    
        getData = async () => {
            this.storedDataA = await get();
            return this.storedDataA;
        }
    }
    
    const instance = new GetSomeData();
    
    console.log(instance.storedDataA);
    console.log(instance.storedDataB);
    
    instance.storedDataB.then((storedDataB) => {
      console.log(instance.storedDataA);
      console.log(storedDataB);
    });

    【讨论】:

      【解决方案2】:

      在第一次尝试中,构造函数启动了一个异步任务并立即返回;创建实例的代码立即运行,太早了看不到结果。在第二次尝试中,构造函数调用了一个在异步操作完成后返回的方法。

      两者都不是明智的。相反,不要在构造函数中进行任何异步(或异步和阻塞),并将异步工作放在实例方法中。

      你仍然可以有缓存...

      class MyClass {
        constructor() {
        }
      
        async getData() {
          if (!this.storedData) {
            this.storedData = await get('url', config)
          }
          return this.storedData
        }
      }
      

      调用者长这样……

      const myInstance = new MyClass()
      const data = await myInstance.getData();
      const dataButQuicker = await myInstance.getData();  // this will get cached data
      

      【讨论】:

      • “构造函数调用了异步操作完成后返回的方法”,实际上异步函数在异步操作完成之前返回,如果没有,代码执行将无法继续,异步行为不会达到。在到达第一个 await 语句后立即返回一个 Promise。最后,该 promise 被解析为函数有效返回的值。
      猜你喜欢
      • 2017-03-04
      • 2016-05-17
      • 2021-02-24
      • 2017-12-23
      • 2021-12-15
      • 1970-01-01
      • 2021-02-19
      • 2014-01-18
      相关资源
      最近更新 更多