【问题标题】:Catch Block in Recursive Function Executing Repeatedly递归函数中的 Catch 块重复执行
【发布时间】:2021-04-01 22:43:31
【问题描述】:

我有一个递归函数,用于从 AWS 上的 CodeCommit 存储库获取 SQL 文件并按顺序运行它们。在运行下一个文件之前,我们需要等待上一个文件完成。如果其中一个 SQL 文件失败,我需要 catch 块来返回有关失败文件的信息。

我目前在代码中看到的是,catch 块对 repo 中的每个 SQL 文件重复一次。据我了解,“throw”语句应该返回到最初调用该函数的函数的 catch 块。谁能指出我在这里做错了什么?

const getFileData = async (newSQLFiles,processed=[]) => {
      try{
        if(newSQLFiles.length ===0){
          client.release();
          await pool.end().then(() => console.log('DB Connection pool closed.'))
          return processed;
        }
    
        var params = {
                filePath: newSQLFiles[0].relativePath, 
                repositoryName: 'testDBScripts' //Use environment variable
              };
    
        const data = await codecommit.getFile(params).promise();
        await runScripts(data);
        processed.push(newSQLFiles[0].relativePath)  
      }catch(err){
        console.log(err)
        throw [err,processed];
      }
      return await getFileData(newSQLFiles.slice(1),processed);
}

await getFileData(newSQLFiles)
.then(processed=>console.log("Following products are updated.",processed))
.catch(async ([e, file])=> {

    client.release();
    await pool.end().then(() => console.log('DB Connection pool closed.'))
    //await codePipelineJobFailed("SQL file " + file + " failed with : " + e)

    throw new Error("SQL file " + file + " failed with : " + e)}
)

【问题讨论】:

    标签: javascript recursion async-await aws-sdk


    【解决方案1】:

    您的代码包含许多关于如何用 JavaScript 编写实用且健壮的异步程序的明显误解。对于下面的代码,我仍有一些地方需要更改,但我无法提供建议,因为未提供有关 codecommit.getFilerunScripts 的信息。如果您对此答案有任何疑问,我很乐意提供帮助 -

    async function getFileData(files) {
      const result = []
      for (const f of files) {
        try {
          const data = await codecommit.getFile({
            filePath: f.relativePath,
            repositoryName: 'testDBScripts'
          }).promise()
          await runScripts(data)
          result.push(f.relativePath)
        }
        catch (e) {
          throw new Error("SQL file " + f + " failed with : " + e.message)
        }
      }
      return result
    }
    

    使用它看起来像这样 -

    getFileData(newSQLFiles)
      .then(console.log, console.error)
      .finally(_ => client.release())
      .finally(_ => pool.end())
    

    或者如果你更喜欢catch,这也是同样的事情-

    getFileData(newSQLFiles)
      .then(console.log)
      .catch(console.error)
      .finally(_ => client.release())
      .finally(_ => pool.end())
    

    注意.finally 回调也可以返回正确排序程序的承诺。请参阅下面的示例 -

    const delay = (ms,x) =>
      new Promise(r => setTimeout(_ => console.log(x) || r(x), ms))
        
    delay(1000,"a")
      .then(_ => delay(1000,"b"))
      .then(_ => delay(200, "result"))
      .finally(_ => delay(500,"client released"))
      .finally(_ => delay(1000,"pool closed"))
      .then(console.log, console.error)
    a
    b
    result
    client released
    pool closed
    result
    

    如果序列中的任何承诺被拒绝或抛出错误,.finally 处理程序仍会被调用 -

    const delay = (ms,x) =>
      new Promise(r => setTimeout(_ => console.log(x) || r(x), ms))
        
    delay(1000,"a")
      .then(_ => Promise.reject(Error("SQL FAILURE")))
      .then(_ => delay(200, "result"))
      .finally(_ => delay(500,"client released"))
      .finally(_ => delay(1000,"pool closed"))
      .then(console.log, console.error)
    a
    client released
    pool closed
    Error: SQL FAILURE
    

    【讨论】:

    • 非常感谢!我对javascript很陌生,所以认为递归方法是按顺序运行代码的唯一方法。 codecommit.getFile 只是一个内置的 aws-sdk 函数,用于从 repo 中提取代码文件。再次感谢!
    【解决方案2】:

    在 JavaScript 中,当一个函数遇到 return 语句时,它将停止函数形式的进一步执行。 可能它目前不起作用,因为在函数中的 catch 之后,您正在返回。

    所以,为了解决您的问题,我愿意这样做:

    
    const getFileData = async (newSQLFiles,processed=[]) => {
          try{
            if(newSQLFiles.length ===0){
              client.release();
              await pool.end().then(() => console.log('DB Connection pool closed.'))
              return processed;
            }
        
            var params = {
                    filePath: newSQLFiles[0].relativePath, 
                    repositoryName: 'testDBScripts' //Use environment variable
                  };
        
            const data = await codecommit.getFile(params).promise();
            await runScripts(data);
            processed.push(newSQLFiles[0].relativePath)  
          }catch(err){
            console.log(err)
            throw [err,processed];
          }
          await getFileData(newSQLFiles.slice(1),processed);
    }
    
    await getFileData(newSQLFiles)
    .then(processed=>console.log("Following products are updated.",processed))
    .catch(async ([e, file])=> {
    
        client.release();
        await pool.end().then(() => console.log('DB Connection pool closed.'))
        //await codePipelineJobFailed("SQL file " + file + " failed with : " + e)
    
        throw new Error("SQL file " + file + " failed with : " + e)}
    )
    

    请注意,我已在 try catch 块之后从函数作用域中删除了 return

    【讨论】:

    • 删除返回后我遇到了同样的问题,但我在 getFileData 调用的 catch 块中不再有文件信息
    猜你喜欢
    • 1970-01-01
    • 2019-08-24
    • 1970-01-01
    • 2022-01-03
    • 2020-04-17
    • 2017-11-26
    • 2011-05-09
    • 2023-03-24
    • 1970-01-01
    相关资源
    最近更新 更多