【问题标题】:NodeJS async/await order not workingNodeJS异步/等待命令不起作用
【发布时间】:2018-07-30 19:52:32
【问题描述】:

我是 NodeJSPromises 的新手,所以我可能不明白它是如何工作的。

我正在我的应用程序中加载一个配置文件,其特点是如果它不存在,我会使用来自数据库调用的信息来创建它。

function getConfig(clientId, app) {
  return new Promise(async (resolve, reject) => {
    await fs.access(config.files.url_networks_file, async function(err) {
      if (err) {
        try {
          await loadClientConfig(clientId);
        } catch (e) {
          reject(e);
        }
      }
    });

    fs.readFile(config.files.url_networks_file, 'utf8', function(err, data) { // Try to read network's configuration file
      if (err) { // If file doesn't exists
        reject(err);
      } else if (JSON.parse(data)[app]) { // In case app's config exists
        resolve(JSON.parse(data)[app]);
      } else { // In case app's config doesn't exists
        reject(new Error('There\'s no configuration for app: ' + app));
      }
    });
  });
}

我的问题是fs.readFile() 不会等到loadClientConfig() 完成,所以它总是返回“找不到文件”。如果配置文件已经存在,则可以正常运行。

我尝试将fs.readFile() 放入fs.access() 回调中,但仍然没有得到任何东西(即使文件存在)。

更新

仍然无法使用我收到的两种解决方案。我正在发布我为每个人制作的代码,以检查我是否在编码中丢失了一些东西:

@昆汀

async function loadClientConfig(clientId) {
    return new Promise((resolve, reject) => {
        fs.access(config.files.url_networks_file, function (err) {
            if (err) {
                try {
                    sql.close();
                    sql.connect(config.database.credentials, function (err) {
                        if (err) {
                            reject(err);
                        } else {
                            var request = new sql.Request();
                            request.input('clientId', clientId);
                            query = config.database.queries.all;

                            request.query(query, function (e, data) {
                                if (e) {
                                    reject(e);
                                } else {
                                    try {
                                        resolve(writeConfigFile(data.recordset));
                                    } catch (err) {
                                        reject(err);
                                    }
                                }
                            });
                        }
                    });
                } catch (e) {
                    reject(e);
                }
            }
        });
    });
};

async function getConfig(clientId, app) {
  return new Promise(async (resolve, reject) => {
    try {
      await loadClientConfig(clientId);
    } catch (e) {
      reject(e);
    }

    fs.readFile(config.files.url_networks_file, 'utf8', function(err, data) { // Try to read network's configuration file
      if (err) { // If file doesn't exists
        reject(err);
      } else if (JSON.parse(data)[app]) { // In case app's config exists
        resolve(JSON.parse(data)[app]);
      } else { // In case app's config doesn't exists
        reject(new Error('There\'s no configuration for app: ' + app));
      }
    });
  });
}

@dasfdsa

async function loadClientConfig(clientId) {
  return new Promise((resolve, reject) => {
    sql.close();
    sql.connect(config.database.credentials, function(err) {
      if (err) {
        reject(err);
      } else {
        var request = new sql.Request();
        request.input('clientId', clientId);
        query = config.database.queries.all;

        request.query(query, async function(e, data) {
          if (e) {
            reject(e);
          } else {              
            try {
              resolve(writeConfigFile(data.recordset));
            } catch (err) {
              reject(err);
            }
          }
        });
      }
    });
  });
};

async function getConfig(clientId, app) {
  await new Promise((resolve, reject) => {
    fs.access(config.files.url_networks_file, async function (err) {
      if (err) {
        try {
          let temp = await loadClientConfig(clientId); /*Now that you told me its async, we will await it as well*/
          resolve(temp);
        } catch (e) {
          reject(e);
        }
      } else {
        resolve();
      }
    });
  });
  let configuration = await new Promise((resolve, reject) => {
    fs.readFile(config.files.url_networks_file, 'utf8', function (err, data) { // Try to read network's configuration file
      if (err) { // If file doesn't exists
        reject(err);
      } else if (JSON.parse(data)[app]) { // In case app's config exists
        resolve(JSON.parse(data)[app]);
      } else { // In case app's config doesn't exists
        reject(new Error('There\'s no configuration for app: ' + app));
      }
    });
  });

  return configuration;
}

更新 2

似乎在调试时有效,我正在使用 VSCode。我认为这可能是超时问题或类似问题。

【问题讨论】:

  • 传递给 fs.access() 的回调让你感到困惑。
  • fs.access 是否返回承诺(提示:否)

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


【解决方案1】:

代码:每个回调有两个单独的awaitedpromisegetConfig 返回一个promise,它将解析为config

async function getConfig(clientId, app) {
    await new Promise((resolve, reject) => {
        fs.access(config.files.url_networks_file, async function (err) {
            if (err) {
                try {
                    let temp = await loadClientConfig(clientId);/*Now that you told me its async, we will await it as well*/
                    resolve(temp);
                } catch (e) {
                    reject(e);
                }
            }
        });
    });
    let config = await new Promise((resolve, reject) => {
        fs.readFile(config.files.url_networks_file, 'utf8', function (err, data) { // Try to read network's configuration file
            if (err) { // If file doesn't exists
                reject(err);
            } else if (JSON.parse(data)[app]) { // In case app's config exists
                resolve(JSON.parse(data)[app]);
            } else { // In case app's config doesn't exists
                reject(new Error('There\'s no configuration for app: ' + app));
            }
        });
    });

    return config;

}

编辑:我已编辑等待loadClientConfig(),如果loadClientConfig 返回一个承诺,上述代码应该可以正常工作。

【讨论】:

  • 感谢您的评论。我会删除它。如果 loadClientConfig(clientId) 有任何错误,它将进入下一个 catch 块,promise 将被拒绝。
  • loadClientConfig 是异步函数吗?
  • 是的,它是一个异步函数。我没有收到任何错误,即使在控制台中也没有。如果我编码错误,我可以用给定的解决方案更新我的答案。
  • 它是否返回一个承诺?如果是,我现在编辑的代码可以正常工作。
  • 我尝试了您的解决方案并进行了一些小的修改,终于让它工作了。原来问题是nodemon,我不知道为什么,但是用node 甚至用de VS Code 启动服务器,工作正常!谢谢!
【解决方案2】:

你只能await一个承诺。

fs.access 不返回承诺(取而代之的是回调)。 (由于您没有在问题中包含该功能,因此无法说出 loadClientConfig 的作用)。

如果你想await 它,那么你需要将它包装在一个返回承诺的函数中。

【讨论】:

  • 我已经尝试移动fs.access但仍然无法正常工作:await loadClientConfig(clientId); fs.readFile(config.files.url_networks_file, 'utf8', function(err, data) { // Try to read network's configuration file ` if (err) { // 如果文件不存在` ` reject(err);` ` } else if (JSON.parse(data)[app]) { // 如果应用的配置存在` ` resolve(JSON.parse(data)[app]);` ` } else { // 如果应用的配置不存在'不存在` `reject(new Error('There\'s no configuration for app: ' + app));` ` }` ` });`
  • @AndrésMarotta — 我说过你需要将 fs.access 包装在一个 Promise 中,但你没有。
  • loadClientConfig 是一个返回promise的函数,这不是你告诉我的吗?我几乎所有的功能都在做,而且工作正常,总是使用 try-catch 块。
  • @AndrésMarotta — 您希望 fs.readFile 等到 fs.access 完成。 fs.access 不返回承诺。
  • 我将发布解决方案以便于查看。
猜你喜欢
  • 2019-01-03
  • 2016-07-07
  • 1970-01-01
  • 1970-01-01
  • 2023-04-07
  • 2019-06-30
  • 1970-01-01
相关资源
最近更新 更多