在函数内初始化一个nodejs全局变量并让它等同于在外部调用它

initializing a nodejs global variable within a function and having it equate the same calling it outside

所以当涉及到 nodejs 时,我在范围方面遇到了一些问题。我想知道如何在全局 space 中初始化变量,在函数(私有范围)中初始化它,然后在 class。我注意到的一件事是,虽然您可以在私有范围内使用该变量,但当它在该函数之外再次调用时,它只会变成未定义的。我怎样才能 return 在私有时初始化相同的函数?这不是我发布的代码,而是一个示例,以防图片不清晰

let name;
class blah {
    static blablah() {
        name = josh;
    }
    console.log(name);
    //this will return undefined and not josh
}

我在我的环境中需要什么:

let genesis;
let jsonChain;

class Blockchain {
    constructor() {
        //this.chain = [Blockchain.getGenesis()];
        console.log(Blockchain.getGenesis());
}
    //down the file we find the issued function...
    static getGenesis() {
         fs.readFile(jsonRoute, 'utf-8', function(err, data) {
             if (err) throw err;
    
             jsonChain = JSON.parse(data);
             genesis = jsonChain.blocks[0].GENESIS_DATA;
             return genesis;
        });
        //returning here instead inside the callback also yields undefined
        //I want to be able to access my contents from json file through 
        //the genesis variable which is global when I return this function
        //but I cannot reach the contents of the callback
    }
}

解决方案:确保 return 承诺,以便异步函数稍后在您的程序中运行。

let genesis;
let jsonChain;

class Blockchain {
    constructor() {
        this.chain = [Blockchain.getGenesis()];
            console.log(Blockchain.getGenesis().then(function(genesisData) {
      console.log(genesisData); // Genesis block data is here.
    }, function(err) {
      // This only runs if there was an error.
      console.log(err);
    }));
        }
    //down the file we find the solved function...
  static getGenesis() {
    return new Promise(function(resolve, reject) {
      fs.readFile(jsonRoute, 'utf-8', function(err, data) {
        if(err) return reject(err);
        const jsonChain = JSON.parse(data);
        resolve(jsonChain.blocks[0].GENESIS_DATA);
      });
    });
  }
    
}
module.exports = Blockchain;

您的代码的第一个问题是 josh 不在引号中。 joshundefined;您是指 'josh'(引号中)吗?


一种方法是让您的 getGenesis() 函数 async,这样您就可以等待它完成为 genesis 分配正确的值。这需要将所有内容包装在匿名 async 函数中:

(async () => { 
  const fs = require('fs');
  let genesis;
  let jsonChain;

  class Blockchain {
    constructor() {
      this.chain = [Blockchain.getGenesis()];
      console.log(Blockchain.getGenesis());
    }

    static async getGenesis() {
      jsonChain = JSON.parse(await fs.promises.readFile(jsonRoute, 'utf-8'));
      genesis = jsonChain.blocks[0].GENESIS_DATA;
    }
  }

  console.log(genesis); // undefined D:
  await Blockchain.getGenesis();
  console.log(genesis); // not undefined :D
})();

现在您已经添加了真正的代码,其中说明了许多问题。

  1. if (err) throw err 在普通异步回调中没有任何用处。没有人可以捕获该错误,因此永远不应该使用它。你需要真正的错误处理。 IMO,在那种情况下永远不应该写那行代码。

  2. return genesis; 没有任何用处。这只是 return 从 fs.readFile() 回调返回,其中 fs.readFile() 的内部忽略任何 return 值。这不是来自更高级别的功能return。

  3. jsonChain = JSON.parse(data); 确实成功地分配给了更高范围的变量,但是任何试图使用 jsonChain 变量的代码都不知道它何时被赋值,因为fs.readFile() 是异步的,并在未来某个不确定的时间调用其回调。所以,如果您看到 jsonChain 没有值,那是因为您在变量被赋值之前查看它。基本上,这是一种反模式。在 node.js 中,您不能以这种方式使用异步代码进行编程。相反,您需要在回调中使用异步值,或者您需要从回调中调用某个函数并将值传递给它。只有在这种情况下,您才知道该值何时可用。

  4. 如果这里的顶级问题是您正在尝试 return 您异步检索的某个值,那么您不能直接在 Javascript 中执行此操作。您可以阅读所有关于 here 的内容,其中解释了您必须通过回调、承诺将异步值传回给调用者,或者您也可以使用事件。