NodeJS Express API 调用结构异步事件
Posted
技术标签:
【中文标题】NodeJS Express API 调用结构异步事件【英文标题】:NodeJS Express API call structure asynchronous events 【发布时间】:2021-09-10 03:35:53 【问题描述】:我正在用 NodeJS 和 Express 做一个爱好项目,但是处理异步调用让我不知所措。我遇到了一个我想在社区中反弹的错误。
我目前使用 Express 进行此布局,我将向其发送帖子请求。
快递(后端)
app.post("/", async (req, res) =>
const createDocument = (args1) =>
// declare some variables ...
// for loop ...
// (quite fast)
loadFile(args2, async () =>
// upload a file (quite slow)
await upload(file, filePath)
//send post request to third party (quite fast)
let res = await axios.post(url, data,
headers:
'X-Auth-Token': KEY
).then(res => console.log('success')).catch(error => console.log('failure'))
)
const args1 = "someargs"
await new Promise(resolve => setTimeout(resolve, 2000))
await createDocument(args1)
res.end()
)
反应(前端)
const saveDocButtonClicked = useCallback(async (event) =>
// do some stuff ...
await axios.post('/',
headers:
'Content-Type': 'application/json'
,
jsonData
).then(res => console.log('Data sent')).catch(err => console.log(err.data))
// do some other stuff ...
我希望 React 应用等待,在从 API 调用到 Express 后端得到正确响应之前不要继续。
我希望 Express 应用仅在完成所有任务后才能给出正确的响应。
到目前为止,这对于较小的文件效果很好,但随着文件大小的增加,它们不再被保存/存储在数据库中。
我注意到的关键区别在于,在这些糟糕的情况下,字符串 success
或 failure
应该来自 Express 后端的这段代码; .then(res => console.log('success')).catch(error => console.log('failure'))
不再被输出。所以在某个地方,异步事件可能会抢先一步。
我确信我犯了很多错误,请随时指出,我很想学习这个,我是异步调用的大一新生。
【问题讨论】:
我认为问题在于createDocument
,您应该从该函数返回承诺,只要loadFile
完成,该函数就会解决。希望有帮助
好的,这在代码中会是什么样子?我有几个想法,但不能写在cmets小窗口里。
【参考方案1】:
您的代码在语法上似乎是正确的(尽管遵循一些 async/await 最佳实践可能会更好 - 但这些不应影响您的应用程序的逻辑)。您能否提供一些示例输入、输出和您的预期输出,以便我更好地理解问题?
同时,我认为可能只是upload()
功能很慢,尤其是对于较大的文件,所以您只需要等待更多时间才能记录“成功”或“失败”
编辑:我想出了一些与异步/等待流程不同的回调流程。似乎 createDocument 没有等待,或者知道等待 loadFile 完成,因为 loadFile 的东西被“隐藏”在回调后面。所以我改变了 createDocument 来返回一个 Promise:
app.post("/", async (req, res) =>
const createDocument = (args1) =>
// Return a promise that waits for loadFile
return new Promise((resolve, reject) =>
// declare some variables ...
// for loop ...
// (quite fast)
loadFile(args, () =>
// I dont like using async with callback, so I'mma use .then()
function makeAxiosRequest()
return axios.post(url, data,
headers:
"X-Auth-Token": KEY,
,
);
// Only resolve createDocument after loadFile's stuff is finished
upload(file, filePath)
.then(() => makeAxiosRequest())
.then(() => console.log("Success"))
.catch((err) => console.log("Failure"))
.finally(resolve());
);
);
;
const args1 = "someargs";
await new Promise((resolve) => setTimeout(resolve, 2000));
await createDocument(args1);
// I like sending something to frontend for better debug experience
return res.json( message: "Respond now ends" );
);
【讨论】:
嘿,我可以使用一些示例输入和输出对原始问题进行编辑。然而奇怪的是,“成功”或“失败”从未被输出,即使在几个小时之后。 我认为您定义 loadFile 函数的方式可能有问题。它看起来既异步又同时使用回调。如果您进行编辑,您能否包含一些有关如何定义 loadFile 函数的详细信息? 该函数实际上不是我定义的,而是我正在使用的包的内置函数,本质上我是用一个长的base64字符串输入它,当它完全加载时,它会触发回调。 我想出了一些与异步/等待流程不同的回调流程。似乎 createDocument 没有等待,或者知道等待 loadFile 完成,因为 loadFile 的东西被“隐藏”在回调后面。你能检查我的编辑看看它是否有效吗? 嘿宝,我一定会检查【参考方案2】:从 createDocument 返回承诺将允许 await createDocument(args1)
等到它完成执行
app.post("/", async (req, res) =>
const createDocument = (args1) =>
return new Promise((resolve,reject)=>
// declare some variables ...
// for loop ...
// (quite fast)
loadFile(args2, async () =>
// upload a file (quite slow)
await upload(file, filePath)
//send post request to third party (quite fast)
let res = await axios.post(url, data,
headers:
'X-Auth-Token': KEY
).then(res => console.log('success')).catch(error => console.log('failure'))
resolve(res);
//TODO:: Reject if some error occurs;
)
);
const args1 = "someargs"
await new Promise(resolve => setTimeout(resolve, 2000))
await createDocument(args1)
res.end()
)
【讨论】:
【参考方案3】:使用 async-await 和 then/catch 是处理这类事情的坏方法。使用 await 你可以完成这项工作
try
const response = await axios.post('/',
headers:
'Content-Type': 'application/json'
,
jsonData
)
// Here is your data after response completed
const data = response.json()
catch(err)
console.log(err)
或者您可以删除 async/await 并简单地使用 then/catch
【讨论】:
以上是关于NodeJS Express API 调用结构异步事件的主要内容,如果未能解决你的问题,请参考以下文章
使用nodejs和rest api调用和express进行异步处理-序列错误
Express 和 Nodejs:调用外部 API 的最佳方式
使用 Express 和 NodeJS 构建 REST API 的最佳实践