【发布时间】:2022-10-15 03:06:02
【问题描述】:
如果第二次发出相同的事件,为什么 Node.js 事件侦听器会“暂停”异步函数的执行以开始第二次执行?第二个问题:如何完成第一次执行,然后开始第二次执行?
即,如果在 Node.js 中启动此代码:
import { EventEmitter } from "events";
let event = new EventEmitter();
event.on("myEvent", async function () {
console.log("Start");
await new Promise((resolve, reject) => {
setTimeout(() => {
resolve(console.log("Do job"));
}, 1000);
});
console.log("Finish");
});
event.emit("myEvent"); // first emit
event.emit("myEvent"); // second emit
然后我得到这样的结果:
Start
Start
Do job
Finish
Do job
Finish
但是我想看到这个:
Start
Do job
Finish
Start
Do job
Finish
更新 下面我放了包含所描述问题的真实代码
const web3 = new Web3(
new Web3.providers.WebsocketProvider(
"wss://eth-mainnet.g.alchemy.com/v2/<API-KEY>"
)
);
let walletAddress = "0x123";
let options = {
topics: [web3.utils.sha3("Transfer(address,address,uint256)")],
};
let subscription = web3.eth.subscribe("logs", options);
subscription.on("data", async (event) => {
if (event.topics.length == 3) {
let transaction = decodeTransaction(event); //just using web3.eth.abi.decodeLog(...)
if (
transaction.from === walletAddress ||
transaction.to === walletAddress
) {
const contract = new web3.eth.Contract(abi, event.address);
let coinSymbol = await contract.methods.symbol().call(); //<-- The issue starts here
await redisClient.hSet(
walletAddress,
coinSymbol,
transaction.value
);
}
}
});
【问题讨论】:
-
那么,您添加的代码到底有什么问题?而且,如果它与
collectData()有关,请也显示该代码。 -
collectData() 只是一个调用另一个异步函数的函数。为了更清楚,我将 collectData() 替换为实际调用的异步函数。据我了解,由于这个函数是异步的,它会在 promise 解析时暂停执行。此时事件侦听器接收到新事件。由于之前的事件还没有完成执行,新的事件以错误的方式执行(因为从数据库中读取了不正确的数据)。
-
也许您想在处理功能周围使用
async-lock之类的东西。 -
但我不确定这甚至是你的问题,因为它看起来好像你正在尝试跟踪余额,但是你实际上做的是为每个钱包保存每个硬币的最后一个已知交易价值(不考虑传入或传出方向)。 - 即便如此,使用符号作为密钥可能不是最好的主意,应该是合约地址 - 原因是我可能会通过部署带有符号
USDT的合约来搞砸你的数据库(这不是真正的 USDT当然是合约)并以这种方式向某人发送 1,000,000 "USDT"。
标签: node.js asynchronous async-await web3js emitter