如何等待函数或数据库查询?然后处理结果,最后发送回去 [英] How to await for a function or a database query? And then process results and finally send them back
问题描述
我有这种情况:
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屋!