J'essaie d'utiliser AWS lambda pour tester quelques appels d'API à l'aide de axios, mais j'ai quelques problèmes. Chaque message que j'ai rencontré disait que la meilleure façon de gérer les promesses dans Lambda était d'utiliser async/await plutôt que .then, alors j'ai fait le changement. Lorsque j'exécute le programme en utilisant node, cela fonctionne parfaitement, mais lorsque j'invoque le Lambda localement, il semble que tout après l'appel axios est ignoré. Lorsque j'invoque le Lambda localement sans await, les appels qui suivent fonctionnent correctement, mais je suis alors obligé d'utiliser .then que le Lambda n'attend pas de toute façon. J'ai augmenté le délai d'expiration Lambda à 900, et j'ai exécuté sam build avant sam invoke local à chaque fois.

function checkServers() {
    console.log("Inside checkServer");
    console.log("Before apis to test");

    // apisToTest has length of 2
    apisToTest.forEach(async (apiToTest) => {
        console.log("Api to test");
        let res = await axios(apiToTest)
        console.log("x"); // This gets skipped
        console.log(res); // This gets skipped
    })
    console.log("After api to test")
}

exports.lambdaHandler = async (event, context) => {
    console.log("Inside lambda handler");
    checkServers();
    console.log("After lambda handler");
};

// Used to test app using node command
checkServers()

Cela donne la sortie suivante:

INFO    Inside lambda handler     
INFO    Inside checkServer        
INFO    Before apis to test       
INFO    Api to test
INFO    Api to test
INFO    After api to test
INFO    After lambda handler
4
Sal 1 nov. 2020 à 11:38

3 réponses

Meilleure réponse

Merci pour toutes vos réponses, malheureusement, ce ne sont pas les solutions idéales pour mon cas d'utilisation, même si elles m'ont été très utiles pour trouver la solution.

async function checkServers() {
    let emailBody = "";
    let callResult = "";
    let completedCalls = 0;
    let promises = [];
    for (const apiToTest of apisToTest) {
        await axios(apiToTest).then((res) => {
            // Do something
        }).catch((r) => {
            // Handle error
        })
    }
}

exports.lambdaHandler = async (event, context) => {
    context.callbackWaitsForEmptyEventLoop = true;
    await checkServers();
};

Pour résumer, j'ai remplacé l'appel forEach par un appel for...of, changé le checkServers en async et combiné await par .then() et { {X6}} pour gérer le résultat Promise. J'ignorais que les deux pouvaient être utilisés pour le faire en tandem. J'espère que cela aidera tous ceux qui ont eu un problème similaire à celui que j'ai eu.

0
Sal 3 nov. 2020 à 05:29

Semblable à ce que dit saart, vous pouvez essayer le code ci-dessous et voir s'il fonctionne:

async function checkServers() {

  const promises = apisToTest.map((apiToTest) => axios(apiToTest))

  const resolvedPromises = await Promise.all(promises);

  return resolvedPromises;
}

exports.lambdaHandler = async (event, context) => {
    try {
      const result = await checkServers();
      console.log(result);
    } catch (error) {
      console.log(error)
    }
    
};

// Used to test app using node command
checkServers();

0
React Dev 3 nov. 2020 à 21:16

Vous avez deux options:

  1. définissez callbackWaitsForEmptyEventLoop sur true - puis AWS attendra que la boucle d'événement soit vide
  2. attendez vos promesses. Notez que vous n'avez pas attendu vos promesses le checkServers. Pensez à utiliser await Promise.all([...]) pour attendre que toutes vos promesses se terminent.

Remarque: Si vous exécutez à nouveau le lambda, les événements des appels précédents peuvent «fuir» vers l'appel suivant. Vous pouvez en savoir plus ici: https: // lumigo.io/blog/node-js-lambda-execution-leaks-a-practical-guide/

Divulgation: je travaille dans l'entreprise qui a publié ce billet de blog

0
saart 1 nov. 2020 à 15:14