最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

node.js - JavaScript Array filter with asyncawait - Stack Overflow

matteradmin4PV0评论

The following function:

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;
}

The filter does not work and all transactions are displayed (console.log), and the filter loops seems to be processed afterwards. I guess it is a async/await problem. How can I keep the the filter synchronous?

The following function:

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;
}

The filter does not work and all transactions are displayed (console.log), and the filter loops seems to be processed afterwards. I guess it is a async/await problem. How can I keep the the filter synchronous?

Share Improve this question asked Apr 19, 2021 at 17:51 HomerHomer 2592 silver badges14 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 11

You can't use an async function as a filter callback, because:

  1. filter won't wait for the promises to be settled, and

  2. async functions always return promises, and promises like all non-null objects are truthy, so as far as filter is concerned you're returning a flag saying you should keep the element

In this case, you can use Promise.all to wait for all the transactions to be retrieved and then filter the results; see ments:

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;
}

All of the calls to web3.eth.getTransaction will be started in parallel, then we wait for all of them to settle via await Promise.all(/*...*/), then filter the result and return it.

Solution below is using iter-ops library, which supports async 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;
            }
        })
    );
}

Function getPendingTransactions will return AsyncIterable<Transaction>, which you can easily loop through:

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

comment list (0)

  1. No comments so far