如何等待函数或数据库查询?然后处理结果,最后发送回去 [英] How to await for a function or a database query? And then process results and finally send them back

查看:105
本文介绍了如何等待函数或数据库查询?然后处理结果,最后发送回去的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这种情况:

app.get('/', async function (request, response) 
{
     await foo(DbConnection).then((result) => console.log("response ready"));
})

let foo = async function (DbConnection)
{
    const myQuery = "SELECT * FROM my_table";

    DbConnection.query(myQuery, async function(err, results) {
       console.log("query ready");
       await bar(results).then((response) => console.log("bar done"))
    })
    return; // go back to app.get() to send stuff to client
}

let bar = async function (results)
{   
    console.log("inside bar");
    await ThirdPartyAPI(result).then((value)) => return value);
}

简要说明:


  • 我收到客户的GET请求

  • I receive GET request from client

我调用foo()查询数据库并在结果上应用函数

I call foo() which query data base and apply functions on results

我使用第三方API处理结果需要时间才能完成

I process results using third party API which takes time to finish

我发送最终结果结果回到客户

I send final results back to client

我期待看到:

查询就绪 - >内部栏 - >完成栏 - >准备好响应

query ready -> inside bar -> bar done -> response ready

但是我看到了:


准备好响应 - >查询就绪 - >内部栏 - >完成栏

response ready -> query ready -> inside bar -> bar done

客户端正在接收 undefined ,因为 response.send()时没有准备就绪

Client is receiving undefined since nothing was ready when response.send()

可能是什么问题?

推荐答案

主要问题在于你的代码是你正在混合 async / await 语法和回调。只有当您想对此函数中的异步调用结果执行某些操作时才使用 async 函数。

The main problem in your code is that you're mixing async/await syntax and callbacks. Use async function only when you want to do something with the result of async call inside this function.

此外,根据您的情况,您需要 promisify connection.query() - 创建一个承诺。请参阅下面带有正常工作代码的正确模式:

Also that, specific to your case, you need to promisify connection.query() - create a promise. See below the correct pattern with a working code:

app.get('/', async (request, response) => {
    // waiting for the result of foo
    let result = await foo();
    console.log("response ready");
});

let foo = async () => {
    const myQuery = "SELECT * FROM my_table";

    // getting the result of the query
    let results = await new Promise((resolve, reject) => connection.query(myQuery, (err, results) => {
      if (err) {
        reject(err)
      } else {
        resolve(results);
      }
    }));
    console.log("query ready");
    // call bar and waiting the result
    let res = await bar(results);
    console.log("bar done");
    // return resolved promise
    return res;
}

let bar = (results) => {   
    console.log("inside bar");
    // just return a promise, we don't need the result here
    return ThirdPartyAPI(result);
}

关于使用 async / await <的说明/ code> 即可。 async / await 的强大之处在于它允许您使用同步语言结构编写异步代码。但这并不意味着所有功能都应标记为 async async 将一个函数包装到一个promise中,如果该函数执行同步代码,这个包装可能会导致错误(例如,您希望该字符串,但函数返回已解析的promise)。另一个例子,当函数执行异步代码,但不使用中间结果时,在这种情况下只需返回异步调用的结果。

Explanation about using async/await. The power of async/await is that it lets you write asynchronous code using synchronous language constructs. But that doesn't mean that all functions should be marked as async. async wraps a function into a promise, if the function executes synchronous code, this wrapping can cause an error (you expect the string for example, but function returns a resolved promise). Another example when the function executes async code, but doesn't use intermediate result, in this case it's enough just return the result of async call.

你应该使用 async / await when:

You should use async/await when:


  • 该函数执行 sync 代码,并且您希望将结果包装到承诺中(用于创建承诺链)。

  • 该函数执行 async 代码,您需要一个中间结果。

  • 该函数执行 async 代码而你需要中间结果,但你想要串行执行代码(用于处理每个例如,数组中的项目。)

  • The function executes sync code, and you want to wrap the result into a promise (for creating a promise chain).
  • The function executes async code and you need an intermediate result.
  • The function executes async code and you don't need an intermediate result, but you want execute code in series (for processing each item in array for example).

让我们考虑一些例子:

1.sync函数,验证 userId validateParams 返回 true / false validateParams2 如果抛出错误 userId 未定义。 validateParams3 返回一个承诺,可用于创建承诺链: validateParams3()。then(...)

1.sync function, validates userId. validateParams returns true/false, validateParams2 throws an error if userId is undefined. validateParams3 returns a promise, and can be used for creating a promise chain: validateParams3().then(...).

let validateParams = (userId) => {
  return userId;
}

let validateParams2 = (userId) => {
  if (!userId) {
    throw new Error('userId is undefined');
  }
}

let validateParams3 = (userId) => {
  if (!userId) {
    return Promise.reject(new Error('userId is undefined'));
  }
  return Promise.resolve();
}

2.async函数,不使用中间结果。 getUser 返回待处理的承诺(当 userId 有效时)或履行承诺(当 userId <时/ code>未定义)。它应该返回一个promise,因为 getUser 可用于启动一个promise链: createUser()。then(...) getUser2 getUser3 做同样的事情,返回一个承诺。这里要求承诺以避免出现 unhandledError 错误,因为 validateParams2 会抛出错误。 getUser2 makred as async (自动创建承诺), getUser3 返回一个承诺。

2.async function, doesn't use intermediate result. getUser returns a pending promise (when userId is valid) or fulfilled promise (when userId is undefined). It should return a promise, because getUser can be used for starting a promise chain: createUser().then(...). getUser2 and getUser3 do the same thing, return a promise. The promise is requred here to avoid getting unhandledError error, because validateParams2 can throw an error. getUser2 makred as async (to create a promise automatically), and getUser3 returns a promise.

let getUser = (userId) => {
  if (validateParams(userId)) {
    return db.getUserById(userId);
  }
  return Promise.resolve();
}

let getUser2 = async (userId) => {
  validateParams2(userId);
  return db.getUserById(userId);
}

let getUser3 = (userId) => {
  return Promise
    .resolve(userId)
    .then(validateParams2)
    .then(() => db.getUserById(userId);
}

3.async function,使用中间结果:

3.async function, uses an intermediate result:

let updateUser = async (userId, userData) => {
  let user = await getUser(userId);
  _.extend(user, userData);

  return db.saveUser(user);
}

上面的函数可以这样使用:

The functions above can be used this way:

// with async
let fn = async (userId, userData) => { 
  try {
    let user = await updateUser(userId, userData);
    console.log(user);
  }
  catch (err) {
    console.log(err);
  }
}

// without async
let fn2 = (userId, userData) => { 
  updateUser(userId, userData)
    .then(user => console.log(user))
    .catch(err => console.log(err))
  }
}

这篇关于如何等待函数或数据库查询?然后处理结果,最后发送回去的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆