繁体   English   中英

嵌套异步等待 function 未在 AWS 中执行 Lambda Function

[英]Nested async await function not executing in AWS Lambda Function

问题:我在使用 async await 函数方面经验很少,我正在尝试在 if-else 语句中执行嵌套的 async await function,该语句依赖于更高级别的 async function 在事件检测时执行。 我希望从嵌套异步 function 获得成功的 http 响应,但我继续获得 null 响应值。 然而,嵌套的异步 function 在 if-else 语句之外按预期工作。 我的目标是简单地获得代码的“等待新承诺”部分,以在条件 if-else 语句中返回 http 响应。 对此的任何帮助表示赞赏。

我尝试了什么:除了搜索具有类似问题的问题外,我还没有真正尝试过任何补救措施,因为我对异步等待函数的性质知之甚少。

代码:

 exports.handler = async (event) => {
    
    const sensorId = event.sensorId;
    
    ddb.scan(params, function (err, data) {
  

    if (err) {
    console.log("Error", err);
  } else {
    console.log("Success", data);
    console.log(typeof(data));
    data.Items.forEach(function (item, index, array) {
      console.log("printing", item);
      console.log('Testing', item.sensorId.S);
      
      if (item.sensorId.S == sensorId) {
          console.log('New sensorId was not created. Already Exists.');
          return ;
      }
      else {
    // Here is the nested async await function
    async () => {
    console.log(event.sensorId);
    const req = new AWS.HttpRequest(appsyncUrl, region);

    const item = {
        input: {
            id: event.sensorId,
            sensorId: event.sensorId
        }
    };

    req.method = "POST";
    req.path = "/graphql";
    req.headers.host = endpoint;
    req.headers["Content-Type"] = "application/json";
    req.body = JSON.stringify({
        query: print(createSensor),
        operationName: "createSensor",
        variables: item
    });
    console.log(typeof(graphqlQuery));
    if (apiKey) {
        req.headers["x-api-key"] = apiKey;
    } else {
        const signer = new AWS.Signers.V4(req, "appsync", true);
        signer.addAuthorization(AWS.config.credentials, AWS.util.date.getDate());
    }
    
    
    const data =  await new Promise((resolve, reject) => {
        const httpRequest = https.request({ ...req, host: endpoint }, (result) => {
            let data = "";

            result.on("data", (chunk) => {
                data += chunk;
            });

            result.on("end", () => {
                resolve(JSON.parse(data.toString()));
            });
        });

        httpRequest.write(req.body);
        httpRequest.end();
    });
  
  


try {
    return {
        statusCode: 200,
        body: data
    };
}

catch(err) {
    console.log('error', err);
}
      };
      
    }});
  }
});

预期结果:

Response
{
  "statusCode": 200,
  "body": {
    "data": {
      "createSensor": {
        "id": "fd78597a-12fd-4bd1-9f9d-6ee1a88e197d",
        "digit": null,
        "date": null,
        "timestamp": null
      }
    }
  }
}

实际结果:

Response
null

您的代码存在一些问题:

  1. 嵌套的异步 function——你正在创建它但从不执行它
async () => { // creates an async anonymous arrow function, that's it

}

两种解决方案:

// wrapping the function in an IIFE create and executes it
(async () => {

})();

// give it a name and execute it later
async main() => {

}

main();
  1. 您可以通过将传递给 forEach 的回调声明为异步来摆脱嵌套的异步 function:
data.Items.forEach(async (item, index, array) => { // <--- this is async
  // ...

  const req = new AWS.HttpRequest(appsyncUrl, region);
  const item = {
    input: {
      id: event.sensorId,
      sensorId: event.sensorId,
    },
  };

  // ...
});
  1. 最后的 try/catch 块不会捕获任何错误。 相反,将您创建的 Promise 包装在一个 try/catch 块中,并在发生错误事件时从内部拒绝:
try {
  const data = await new Promise((resolve, reject) => {
    const httpRequest = https.request(
      { ...req, host: endpoint },
      (result) => {
        // ...

        result.on("error", (error) => {
          reject(error);
        });

        // ...
      }
    );

    // ...
  });

  return {
    statusCode: 200,
    body: data,
  };
} catch (err) {
  console.log("error", err);
}
  1. 在 forEach 内部运行异步操作不会执行您打算执行的操作。 您可能打算在创建所有 sensorsId进行响应。 真正发生的是您在创建第一个 sensorId 后立即做出响应。 这是因为 forEach 会同时触发data.Items的回调。 一个解决方案是改用 map 并返回一个 Promise 数组,然后您可以使用 Promise.all 等待它。

这是最终代码以及我将如何解决它。 作为额外的,我已经承诺了ddb.scan ,这样你就不会将回调与承诺和异步/等待混在一起:

const scanAsync = util.promisify(ddb.scan);

exports.handler = async (event) => {
  const sensorId = event.sensorId;

  try {
    const data = await scanAsync(params);

    const responses = await Promise.all(
      data.Items.map((item) => {
        if (item.sensorId.S == sensorId) {
          console.log("New sensorId was not created. Already Exists.");
          return;
        }

        const req = new AWS.HttpRequest(appsyncUrl, region);
        const item = {
          input: {
            id: event.sensorId,
            sensorId: event.sensorId,
          },
        };

        req.method = "POST";
        req.path = "/graphql";
        req.headers.host = endpoint;
        req.headers["Content-Type"] = "application/json";
        req.body = JSON.stringify({
          query: print(createSensor),
          operationName: "createSensor",
          variables: item,
        });

        if (apiKey) {
          req.headers["x-api-key"] = apiKey;
        } else {
          const signer = new AWS.Signers.V4(req, "appsync", true);
          signer.addAuthorization(
            AWS.config.credentials,
            AWS.util.date.getDate()
          );
        }

        return new Promise((resolve, reject) => {
          const httpRequest = https.request(
            { ...req, host: endpoint },
            (result) => {
              let data = "";

              result.on("data", (chunk) => {
                data += chunk;
              });

              result.on("error", (error) => {
                reject(error);
              });

              result.on("end", () => {
                resolve(JSON.parse(data.toString()));
              });
            }
          );

          httpRequest.write(req.body);
          httpRequest.end();
        });
      })
    );

    return {
      statusCode: 200,
      body: responses,
    };
  } catch (error) {
    console.log("error", error);
  }
};

我希望你从我的回答中学到一两件事:)。 如果您有任何问题,请告诉我。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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