简体   繁体   中英

Loop with await

I want to run the following code:

const express = require('express');
const app = express();

app.post('/getTransaction', (req,res) => {
  let transaction = getTransaction(req.body.id);

  let logs = getEncodedLogs(transaction.logs);
  console.log('SEND'); // Gets called before getEncodedLogs() returns Array
  return res.send(Object.assign(transaction, { logs }));
});

async function getEncodedLogs(logs) {
  let logsDecoded = [];
  await Promise.all(logs.map(async (log) => {
    logsDecoded.push({
      logIndex: log.logIndex,
      data: log.data,
      topics: log.topics
    });
  }));
  console.log(logsDecoded);
  return logsDecoded;
}

app.listen(process.env.PORT || 8000);

The issue I'm having is that res.send(Object.assign(transaction, { logs })); gets run before getEncodedLogs() has returned the processed Array . I could rewrite it to let logs = await getEncodedLogs(transaction.logs); but that would block the process. Is there a better way?

getEncodedLogs(transaction.logs) doesn't return your logs, it returns a Promise that resolves to your logs when it has finished 1 . The simplest way of getting this to work as expected would be to add a .then callback:

app.post('/getTransaction', (req, res) => {
    let transaction = getTransaction(req.body.id);

    getEncodedLogs(transaction.logs).then(logs => {
        console.log('SEND');
        res.send(Object.assign(transaction, { logs }));
    });
});

1. as all async functions do - the await syntax is just a convenient way of saying 'wait for this promise to finish before you carry on executing this function, please'

So currently nothing in this example is actually async or needs to involve a Promise. getTransactions might but without seeing the implementation I can't tell. So therefore the answer could be represented like this

const express = require('express');
const app = express();

app.post('/getTransaction', (req,res) => {
  let transaction = getTransaction(req.body.id);

  let logs = getEncodedLogs(transaction.logs);
  console.log('SEND'); // Gets called before getEncodedLogs() returns Array
  return res.send(Object.assign(transaction, { logs }));
});

function getEncodedLogs(logs) {
  return logs.map((log) => {
    return {
      logIndex: log.logIndex,
      data: log.data,
      topics: log.topics
    };
  }));
}

app.listen(process.env.PORT || 8000);

If we dive deeper and look at the following part of the question

let logsDecoded = [];
await Promise.all(logs.map(async (log) => {
  logsDecoded.push({
    logIndex: log.logIndex,
    data: log.data,
    topics: log.topics
  });
}));

logDecoded is just a normal array and therefore the async function within map is actually not async.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM