【问题标题】:How to wait for inner function to complete before returning the outer function?如何在返回外部函数之前等待内部函数完成?
【发布时间】:2020-09-25 17:56:35
【问题描述】:

我正在创建一个从 NodeJS AWS 开发工具包的 EC2.describeInstanceStatus 方法返回数据的函数。这是它的样子:

function getInstanceDetails(): sdk.EC2.DescribeInstancesResult[] {
  let instanceDetails: sdk.EC2.DescribeInstancesResult[] = [];
  let ec2Query = new sdk.EC2();

  ec2Query.describeInstanceStatus(
      function (err, data): void {
          if (err) console.log(err, err.stack);
          else {
              instanceDetails.forEach(instance => {
                  instanceDetails.push(instance);
              });
              console.log(data);
          }
       });

  return instanceDetails;
}

我发现我的函数返回一个空数组,这似乎是因为它上面的回调在return语句执行之前没有执行完。

虽然我知道这一点,但我不确定如何确保回调函数在返回结果之前完成

关于如何实现这一点的任何想法?

在此处阅读有关describeInstanceStatus 方法的更多信息:https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/EC2.html#describeInstanceStatus-property

【问题讨论】:

  • 也许,你可以使用内部返回回调,所以无论何时调用,外部函数都可以完成。

标签: node.js typescript amazon-web-services aws-sdk aws-sdk-nodejs


【解决方案1】:

因为这个操作是异步的,所以你必须使用 Promises 或者 async/await 函数。以下是使用任一选项重写它的方法:

承诺:

function getInstanceDetails(): Promise<sdk.EC2.DescribeInstancesResult[]> {
  let instanceDetails: sdk.EC2.DescribeInstancesResult[] = [];
  let ec2Query = new sdk.EC2();

  return new Promise((resolve, reject) => {
    ec2Query.describeInstanceStatus((err, data) => {
      // This will reject the promise in case of error
      // If this happens, callback provided to `.catch` will be fired
      if(err) return reject(err)

      // This happens on success, callback in `.then` will be called
      resolve(data)
    })
  }).then((data) => {
    // Did you mean to do `data.forEach` here? This code
    // seems a bit weird, but I'm not sure, what you want
    instanceDetails.forEach(instance => {
      instanceDetails.push(instance);
    });
    console.log(data);
    
    // This value then can be used by consumers of `getInstanceDetails` function
    return instanceDetails
  }).catch((err) => {
    console.error(err, err.stack)
  })
}

异步/等待:

async function getInstanceDetails(): Promise<sdk.EC2.DescribeInstancesResult[]> {
  let instanceDetails: sdk.EC2.DescribeInstancesResult[] = [];
  let ec2Query = new sdk.EC2();

  try {
    const data = await new Promise((resolve, reject) => {
      ec2Query.describeInstanceStatus((err, data) => {
      // Analog of throwing an error, `catch` block will be fired
      if(err) return reject(err)
      // Becomes return value of `await new Promise`
      resolve(data)
    })
    instanceDetails.forEach(instance => {
      instanceDetails.push(instance);
    });
    console.log(data);
    
    // This value will can be used by consumers of `getInstanceDetails` function
    return instanceDetails
  } catch(e) {
    console.error(e, e.stack)
  }
}

处理异步操作的唯一方法是回调函数,但您可以在互联网上阅读,与 Promises 相比,它们为什么不好。

缺点是现在所有使用getInstanceDetails 的函数都必须使用promise 或async/await 语法:

getInstanceDetails().then(instanceDetails => {
  // Do something with instanceDetails
})

async function doSomething() {
  const instanceDetails = await getInstanceDetails()
  // Do something with instanceDetails
}
doSomething()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-01
    • 1970-01-01
    相关资源
    最近更新 更多