为什么即使解决了Promise,在这个Node JS示例中也从未执行.then()?

时间:2019-06-21 15:16:25

标签: node.js aws-sdk es6-promise

我是Node的新手,并遵循Ryan Lewis的关于高级使用AWS Javascript SDK的出色课程。我编写的代码根据说明运行并且可以正常运行,甚至可以连接到AWS并按预期创建安全组。此后,可以解析返回的promise,并通过创建密钥对和最后的实例来继续。如果有错误,则有望被捕获。

但是,决不会执行在末尾使用.then().catch()语句传递给promise的resolve(或reject)函数中的代码,这是不希望的。

我尝试过:

  • 稍微重组代码
  • 添加一些日志记录
  • 在末尾添加setInterval(),以防止节点退出

这是我的代码:

// Imports
const AWS = require('aws-sdk')
const proxy = require('proxy-agent')
const helpers = require('./helpers')

AWS.config.update({
  region: 'eu-central-1'
})

console.log(AWS.config)

// Declare local variables
const ec2 = new AWS.EC2()
const sgName = 'hamster_sg'
const keyName = 'hamster_key'

// Create functions
function createSecurityGroup(sgName) {
  const params = {
    Description: sgName,
    GroupName: sgName
  }

  return new Promise((resolve, reject) => {
    ec2.createSecurityGroup(params, (err, data) => {
      if (!err) {
        const params = {
          GroupId: data.GroupId,
          IpPermissions: [
            {
              IpProtocol: 'tcp',
              FromPort: 22,
              ToPort: 22,
              IpRanges: [
                {
                  CidrIp: '0.0.0.0/0'
                }
              ]
            },
            {
              IpProtocol: 'tcp',
              FromPort: 3000,
              ToPort: 3000,
              IpRanges: [
                {
                  CidrIp: '0.0.0.0/0'
                }
              ]
            }
          ]
        }
        ec2.authorizeSecurityGroupIngress(params, err => {
          console.log('Creating Security Group.')
          if (!err) {
            console.log('Calling Resolve.')
            resolve
          } else {
            reject(err)
          }
        })
      } else {
        reject(err)
      }
    })
  })
}

function createKeyPair(keyName) {
  const params = {
    KeyName: keyName
  }

  return new Promise((resolve, reject) => {
    ec2.createKeyPair(params, (err, data) => {
      if (!err) {
        resolve(data)
      } else {
        reject(err)
      }
    })
  })
}

function createInstance(sgName, keyName) {
  const params = {
    ImageId: 'ami-026d3b3672c6e7b66',
    InstanceType: 't2.micro',
    KeyName: keyName,
    MaxCount: 1,
    MinCount: 1,
    SecurityGroups: [sgName],
    UserData:
      'IyEvYmluL2Jhc2gKY3VybCAtLXNpbGVudCAtLWxvY2F0aW9uIGh0dHBzOi8vcnBtLm5vZGVzb3VyY2UuY29tL3NldHVwXzgueCB8IHN1ZG8gYmFzaCAtCnN1ZG8geXVtIGluc3RhbGwgLXkgbm9kZWpzCnN1ZG8geXVtIGluc3RhbGwgLXkgZ2l0CmdpdCBjbG9uZSBodHRwczovL2dpdGh1Yi5jb20vdGl0dXNuL2hhbXN0ZXJjb3Vyc2UuZ2l0CmNkIGhiZmwKbnBtIGkKbnBtIHJ1biBzdGFydAo='
  }

  return new Promise((resolve, reject) => {
    ec2.runInstances(params, (err, data) => {
      if (!err) {
        resolve(data)
      } else {
        reject(err)
      }
    })
  })
}

// Do all the things together
createSecurityGroup(sgName)
  .then(
    () => {
      console.log('SecurityGroup Created.')
      return createKeyPair(keyName)
    },
    err => {
      console.error('Failed to create instance with:', err)
    }
  )
  .then(helpers.persistKeyPair)
  .then(() => {
    console.log('Keypair Created.')
    return createInstance(sgName, keyName)
  })
  .then(data => {
    console.log('Created instance with:', data)
  })
  .catch(err => {
    console.error('Failed to create instance with:', err)
  })

setInterval(function() {
  return console.log("I'm still running!")
}, 1000)

这是输出:

Creating Security Group.
Calling Resolve.
I'm still running!
I'm still running!
I'm still running!
I'm still running!
I'm still running!

节点版本为10.16.0

当我在IntelliJ中在打印“ Calling Resolve”的行上设置断点时。然后我看到以下内容:

Variables pane in IntelliJ

这就是我有点迷茫的地方。我看不到resolve函数是否设置正确。有什么办法吗?但更重要的是:我想念什么?看来我似乎并没有做任何特别的事情(除了可能省去了所有的分号,而这些附加的分号和漂亮使我做到了)。因此,问题很简单:为什么即使我很好地调用then(),在代码末尾的所有resolve调用也都不会执行?非常感谢您的帮助。

1 个答案:

答案 0 :(得分:3)

在此过程中,将public class Runner { public static void main(String[] args) throws Exception { args2 = new String[] { path + "/features", "--glue", "stepFiles", "--threads", threadsQty, "", "--tags", tags}; cucumber.api.cli.Main.run(args2,Thread.currentThread().getContextClassLoader()); } @Before public void beforeScenario() { System.out.println("This will run before the Scenario"); } @After public void afterScenario() { System.out.println("This will run after the Scenario"); } } 更改为resolve

resolve()

因此它变为:

    ec2.authorizeSecurityGroupIngress(params, err => {
      console.log('Creating Security Group.')
      if (!err) {
        console.log('Calling Resolve.')
        resolve
      } else {
        reject(err)
      }

您必须实际调用该函数。仅将 ec2.authorizeSecurityGroupIngress(params, err => { console.log('Creating Security Group.') if (!err) { console.log('Calling Resolve.') resolve() // <===== change here } else { reject(err) } 放入代码中,如果没有后面的括号也无济于事。


仅供参考,通常认为,将“使用”功能与使用“分开”(在外部创建“返回承诺”的单独功能/方法)是“简洁”的,这样,您的主要编码逻辑和控制流程仅会显示“承诺”操作,而不是内嵌的Promise和回调的组合。

此外,对于遵循带有参数resolve的回调的node.js异步调用约定的函数(这只是您正在使用的一些异步函数),您可以使用util.promisify()来进行创建功能/方法的承诺版本,而无需手动编写每个功能/方法。