【问题标题】:accessing value of variable outside of async/await iife [duplicate]访问 async/await iife 之外的变量值 [重复]
【发布时间】:2022-01-10 03:43:45
【问题描述】:

我有下面的代码。我需要在其他函数中使用 con 的值,但对此我没有可能的解决方案。我尝试使用 .thens 并像其他堆栈文章一样等待,但我不断收到 con 无效的错误。

我真的被困住了,不确定如何处理。

service.js

async function connectToDatabase(secret) {
  
  try {
      const secretValue = await getSecretPromise(secret)

      const { host, port, username, password, dbname } = JSON.parse(secretValue);

      let con = mysql.createConnection({
          host: host,
          port: port,
          user: username,
          password: password,
          database: dbname
      });
      con.connect(function(err) {
        if (err) throw err;
        console.log("Connected to database!");
      });
      return con;
  } catch (error) {
      console.error(error)
  }
}

// Start an IIFE to use `await` at the top level
(async function(){
  let con = await connectToDatabase(secretName);
})();

function createUser({ data }) {
  return new Promise((resolve, reject) => {
    var sql = `query`;
    con.query(sql, function (err, result) {
      //does not work currently because ReferenceError: con is not defined
    });
  });
}

controller.js

async function getUsers(req, res, next) {

    service.getUsers().then(function(val) {
        res.json(val)
    });
}

getsecretpromise

function getSecretPromise(secretName) {
  return new Promise((resolve, reject) => {
    client.getSecretValue({SecretId: secretName}, function(err, data) 

    {
      //do stuff
    }
    }

service.getUsers

//this is in service.js
module.exports = {
  createUser,
  getUsers,
  patchUser,
  loginUser,
  updateCallForward,
  getEmail,
  getCallForwardingNumber,
  getDB
};

function getUsers() {
  return new Promise((resolve, reject) => {

    var sql = `sql`;

    getDB().then(con => {
      con.query(sql, function (err, result) {
        if (err) throw err;
        resolve(result);
      });
    });

  });
}

【问题讨论】:

  • 为什么secretName 是一个承诺?
  • @LucaKiebel wdym
  • const secretValue = await getSecretPromise(secret) 为什么这是一个承诺?似乎这是你必须在这里使用承诺的唯一原因
  • 因为我从 API 获取值,所以我需要 @LucaKiebel
  • @LucaKiebel 更新了更多信息

标签: javascript node.js asynchronous async-await promise


【解决方案1】:

您在 con 变量被返回后定义它,您的 IIFE 在读取后开始工作。我想说的是您需要将该功能向上移动,如果这不是一个选项,那么您需要在返回它之前定义 con 。如果你已经在这个函数之前定义了它,那我不知道。

async function connectToDatabase(secret) {
  
    // Start an IIFE to use `await` at the top level
    (async function(){
      let con = await connectToDatabase(secretName);
    })();

    try {
        const secretValue = await getSecretPromise(secret)

        const { host, port, username, password, dbname } = JSON.parse(secretValue);

        let con = mysql.createConnection({
            host: host,
            port: port,
            user: username,
            password: password,
            database: dbname
         });
         con.connect(function(err) {
             if (err) throw err;
             console.log("Connected to database!");
         });
         return con;
    } catch (error) {
          console.error(error)
    }
}

function createUser({ data }) {
    return new Promise((resolve, reject) => {
        var sql = `query`;
        con.query(sql, function (err, result) {
        //does not work currently because ReferenceError: con is not defined
    });
  });
}

【讨论】:

  • 不幸地尝试了所有这些。
  • 您是否也尝试将 con 函数放在 connectToDatabase 函数之前?
【解决方案2】:

理想情况下,您会做这样的事情。这将从其余代码中隐藏您的实例(在这种情况下并非如此),因为您将通过 getter 函数访问它。当然,您需要将您的秘密作为常量导入。除非您有多个 db,否则将其作为参数传递是没有意义的

let con = null;

async function connectToDatabase(secret) {

    try {
        const secretValue = await getSecretPromise(secret)

        const { host, port, username, password, dbname } = JSON.parse(secretValue);

        con = mysql.createConnection({
            host: host,
            port: port,
            user: username,
            password: password,
            database: dbname
        });
        con.connect(function (err) {
            if (err) throw err;
            console.log("Connected to database!");
        });
        return con;
    } catch (error) {
        console.error(error)
        con = null;
    }
}

export async function getDB() {
    if (con == null) {
        let secretObj = {};
        return await connectToDatabase(secretObj);
    }
    else {
        return Promise.resolve(con);
    }
}

export function createUser({ data }) {
    return new Promise((resolve, reject) => {
        var sql = `query`;
        getDB().then(con => {
            con.query(sql, function (err, result) {
                //does not work currently because ReferenceError: con is not defined
            });
        });
    });
}

【讨论】:

  • 这给了我一个错误。导出异步函数 getDB() { ^^^^^^ SyntaxError: Unexpected token 'export'
  • 你可能使用的是旧版本的 js。将所有export 替换为module.exports =
  • 没有抛出错误,但我收到一个待处理的请求
  • 看上面的新图片
  • service.getUsers() 的代码在哪里?
【解决方案3】:

可以通过制作 mysql 回调样式函数的承诺返回版本来简化(和修复)代码...

async function connect(connection) {
   return new Promise((resolve, reject) => {
     connection.connect(function (err) {
       err ? reject(err) : resolve(connection)
     });
   })
}

async function query(connection, query) {
  return new Promise((resolve, reject) => {
   connection.query(query, function (err, results, fields) {
     err ? reject(err) : resolve({results, fields});
   });
 });
}

只有这些函数才能显式创建新的 Promise。这会清理connectToDatabase 函数...

async function connectToDatabase(secret) {
  try {
      const secretValue = await getSecretPromise(secret)
      const { host, port, username, password, dbname } = JSON.parse(secretValue);

      let con = mysql.createConnection({
          host: host,
          port: port,
          user: username,
          password: password,
          database: dbname
      });
      return await connect(con);
  } catch (error) {
      console.error(error)
  }
}

它基本上清理了createUser...

async function createUser({ data }) {
  try {
    const connection = await connectToDatabase(secretName);
    let {results, fields} = query(connection, 'query');
    // and so on
   
  } catch(error) {
    console.log(error);
  }
}

并不是getSecretPromise() 可能需要相同的处理,但在 OP 中并未完全指定。

其他注意事项:未经测试(甚至未编译)。依赖范围内的值,其定义未在 OP 中显示(例如 secretName)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-24
    • 1970-01-01
    • 1970-01-01
    • 2020-06-06
    • 1970-01-01
    • 1970-01-01
    • 2015-04-20
    相关资源
    最近更新 更多