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

6

下面的函数:

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),并且过滤器循环似乎是在之后处理的。我猜这是一个async/await问题。如何保持过滤器同步?
2个回答

10

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

  1. filter不会等待承诺被解决,

  2. async函数总是返回承诺,而像所有非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(/*...*/) 等待它们都完成,然后筛选结果并返回。


0
下面的解决方案使用 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
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接