NodeJS 使用async/await的JavaScript数组过滤器

vof42yt1  于 2022-12-12  发布在  Node.js
关注(0)|答案(2)|浏览(183)

以下功能:

async function getPendingTransactions(address){
    var pendingBlock = await web3.eth.getBlock('pending');
    var i = 0;
    var pendingTransactions = await pendingBlock.transactions.filter(async function(txHash)  {
        var tx = await web3.eth.getTransaction(txHash);
        console.log(tx);
        if(tx != null) {
            return tx.from==address && tx.to == CONTRACT_ADDRESS;
        }
    });
    console.log(pendingTransactions);   
    return pendingTransactions;
}

过滤器不起作用,所有的事务都显示出来了(console.log),过滤器循环似乎是在之后处理的。我猜这是一个异步/等待问题。我如何保持过滤器同步?

vojdkbi0

vojdkbi01#

不能将async函数用作filter回调函数,因为:

  1. filter不会等待承诺得到解决,并且
  2. async函数总是返回promises,而promises就像所有非null对象一样都是真实的,因此就filter而言,您返回的是一个标志,表示您应该保留该元素
    在这种情况下,可以使用Promise.all等待检索所有事务,然后筛选结果;参见注解:
async function getPendingTransactions(address) {
    const pendingBlock = await web3.eth.getBlock("pending");
    // *** Get the transactions by creating an array of promises and then waiting
    // via `await` for all of them to settle
    const transactions = await Promise.all(
        pendingBlock.transactions.map(txHash => web3.eth.getTransaction(txHash))
    );
    // *** Filter them
    const pendingTransactions = transactions.filter(
        tx => tx && tx.from == address && tx.to == CONTRACT_ADDRESS
    );
    return pendingTransactions;
}

web3.eth.getTransaction的所有调用都将并行启动,然后我们等待所有调用通过await Promise.all(/*...*/)完成,然后过滤结果并返回。

yjghlzjz

yjghlzjz2#

下面的解决方案使用iter-ops库,该库支持异步filter

async function getPendingTransactions(address) {
    const pendingBlock = await web3.eth.getBlock('pending');
    return pipeAsync(
        pendingBlock.transactions,
        filter(async txHash => {
            const tx = await web3.eth.getTransaction(txHash);
            console.log(tx);
            if(tx != null) {
                return tx.from == address && tx.to == CONTRACT_ADDRESS;
            }
        })
    );
}

函数getPendingTransactions将返回AsyncIterable<Transaction>,您可以轻松地循环执行该函数:

for await (const t of getPendingTransactions('address')) {
    console.log(t); // transaction details
}

相关问题