【问题标题】:Returning value from async function node.js从异步函数 node.js 返回值
【发布时间】:2020-09-12 02:06:53
【问题描述】:

我知道这是 javascript 中关于函数异步行为的最常见问题。我仍然无法为我的用例找到可行的解决方案。 我想做的是使用一个键查找redis缓存。我正在使用 exists 函数来检查密钥是否存在。如果存在,那么我将从缓存中返回,如果没有,那么我将设置密钥,然后使用此密钥作为数据库参数进行数据库调用。这似乎很简单,但无论我做什么,我都无法从缓存或数据库中返回值。如果我在现有函数之外进行这些调用,那么它作为解析器函数(graphql 解析器)是一个异步函数。这个解析器函数需要一个返回值。 所以这是我无法在任何情况下重新调整值的代码:-

empId: async(obj, params, ctx, resolverInfo) => {

    await client.exists(obj.empId, async function(err, reply) {
      if (reply == 1) {

        return await getAsync(obj.empId).then(res => {
          console.log(res);
          return res;

        })
      } else {
        return await db.one('SELECT * FROM iuidtest WHERE empid = $1', [obj.empId])
          .then(iuidtest => {
            console.log(iuidtest.empid);
            return iuidtest.empid;
          })

      }
    });

    const doSomethingWith = empid => {

      console.log("empid = ", empid);

    }

我在控制台中获得了正确的值,但无法返回。但是,如果我直接在我的解析器函数中进行这些调用,即在 redis 存在函数之外,我可以返回该值。

empId: async(obj, params, ctx, resolverInfo) => {
    return await getAsync(obj.empId).then(res => {
          console.log(res);
          return res;

这样我就可以从解析器函数返回值。如果有人可以为此提供工作代码而不是其他有关如何使用回调和承诺从异步函数返回的链接,那将非常有帮助。这是另一个相同的帖子。 :- Redis async library does not have function that are in redis library for node.js 提前致谢!

【问题讨论】:

  • await clients.exists() 仅在该函数返回承诺时才有效。根据您的代码,它需要一个回调函数,这意味着它不会返回承诺,并且您的代码不会等待任何东西。您需要承诺 client.exists() 调用。
  • "任何人都可以为此提供工作代码" 欢迎来到 Stack Overflow。请注意,这不是免费的编码服务。另外,请您在this中解释一下您看不懂的部分,以便其他人帮助您。
  • @Zukerberg 好的,抱歉,我引用错误。我实际上被困在我的存在函数中以及如何使用承诺的部分,以便无论如何我都能够从中返回响应。
  • @Chris G 我尝试承诺存在函数,但无法返回响应。我也不明白为什么this可以在exist函数之外返回,而不能在它的回调函数内部返回?

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


【解决方案1】:

如果client.exists返回promise,同样的代码可以写成如下:

empId: async (obj, params, ctx, resolverInfo) => {

    const exists = await client.exists(obj.empId);

    if (exists === 1) {
      return getAsync(obj.empId);
    }

    return await db.one('SELECT * FROM iuidtest WHERE empid = $1', [obj.empId])
      .then(iuidtest => {
        return iuidtest.empid;
      });

  }

如果client.exists只接受回调,那么代码可以写成:

empId: async (obj, params, ctx, resolverInfo) => {

    async function empIdExists(empId) {

      return new Promise(function resolver(resolve, reject) {

        client.exists(obj.empId, function(err, reply) {

          if (err) {
            reject(err);
            return;
          }

          if (reply == 1) {
            resolve(1);
            return;
          } else {
            resolve(0);
            return;

          }

        })

      });

    }

    const exists = await empIdExists(obj.empId);

    if (exists === 1) {
      return getAsync(obj.empId);
    }

    return await db.one('SELECT * FROM iuidtest WHERE empid = $1', [obj.empId])
      .then(iuidtest => {
        return iuidtest.empid;
      });

  }

在第二个版本中,请注意我已将 client.exists 调用包装到异步函数中并使用 await 关键字调用。

【讨论】:

  • 这正是我想要的!非常感谢。在尝试承诺时,我没有将调用包装到异步函数中,然后使用 await 对该异步函数进行调用。这就是为什么我想在解析器中返回相同的 redis 和 db 查找,因为它是异步的?虽然我对异步函数和 Promise 的使用还不是很清楚。如果您可以建议新手从哪里开始,那将非常有帮助。
  • 简单易懂。 async 函数是内部承诺函数。 async/await 是使用 Promise 构造函数的语法糖。如果函数返回 promise,则可以使用 await 关键字调用它。如果一个函数是一个async 函数,即:如果有async 关键字前缀,那么你可以在那个函数调用上做.then(...)。所以,如果你知道一个函数返回一个 Promise,请在调用该函数时随意输入 await 关键字。那里没有什么要学的了。
  • 我建议你写一些简单的 promise 函数和异步函数,并以 promise 和 async/await 的方式调用它们来理解动态。
猜你喜欢
  • 1970-01-01
  • 2022-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-29
相关资源
最近更新 更多