适当的 node.js 抽象以防止在访问以太坊区块链时出现竞争条件

Proper node.js abstractions to prevent race conditions when accessing ethereum blockchain

我正在使用 web3 版本 1.0.0-beta.27,其中对区块链的所有访问都是异步的,显然这会带来竞争条件的可能性,即:

var Web3 = require("web3");     

// connect to etherum blockchain
var ether_port = 'http://localhost:8545'
var web3       = new Web3(new Web3.providers.HttpProvider(ether_port));


// this is how we set the value, note there is the possiblity of race condidtions here
var accounts = []

web3.eth.getAccounts().then(function(accts){
    console.log("printing account: ", accts)
    accounts = accts
})

// observe race condition
console.log("assert race condition: ", accounts[0])

上面最后一行是人为的,它是为了证明我想在评估后使用accounts。即,最终我想要 modify/read 来自前端 express.js 网络应用程序甚至移动应用程序的区块链,所以为了严谨起见,node.js 中的常用工具是什么确保竞争条件永远不会发生?这些工具存在吗?如果不是,有哪些常见做法。我也是 node.js 的新手。

一个想法是不要尝试直接存储数据,因为由于异步结果的不确定性,尝试访问数据的代码不知道数据何时有效。因此,您存储 promise 和任何想要访问数据的代码,只需在 promise 上使用 .then()/.catch() 即可。无论异步时间如何,这将始终有效。如果数据已经存在,将快速调用 .then() 处理程序。如果数据还没有,那么调用者将排队等待数据到达时得到通知。

let accountDataPromise = web3.eth.getAccounts().then(function(accts){
    console.log("printing account: ", accts)
    return accts;
});

// then, elsewhere in the code
accountDataPromise.then(accts => {
    // use accts here
}).catch(err => {
    // error getting accts data
});

仅供参考,将数据从 .then() 处理程序分配给您希望在承诺链之外的其他代码中通常使用的更高范围的变量几乎总是麻烦代码的标志 - 不要这样做。这是因为承诺链之外的其他代码不知道该数据何时有效。