javascript - 在以 express 呈现视图后更新视图中的消息(一旦执行异步代码)
问题描述
我正在构建一个小型快速应用程序,它基本上只是从目录中读取文件重命名它们然后压缩文件,现在文件的读取和重命名部分是同步完成的,压缩部分是异步完成的,然后我的应用程序呈现另一个视图,所以我的逻辑如下:
/*
// file read and renaming code here
*/
// Zip files code below:
try {
let files_converted = fs.readdirSync(OUTPUT_DIRECTORY);
let file_converstion_async_array = [];
files_converted.forEach( (e , i) => {
file_converstion_async_array.push( () => zip_Directory( `${OUTPUT_DIRECTORY}/${e}` , `${OUTPUT_DIRECTORY}/${e}.zip` ) );
});
console.log('Files are being zipped...');
file_converstion_async_array.reduce( ( promise_chain , current_promise ) => {
return promise_chain.then( p_results => {
return current_promise().then( c_result => {
// console.log('ZIPPED');
});
});
} , Promise.resolve([]) ).then( () => {
console.log('All Files have been zipped...');
});
} catch (err) {
console.error(err);
}
// Finally render a new view
res.render("finish", {
name: req.body.outputPath
});
现在发生的是同步代码运行,然后呈现新视图,然后异步代码继续在后台运行。我想做的是,一旦执行异步代码以使用新消息更新我的视图,我怎么能在不显示另一个新视图的情况下做到这一点(我不确定这是可能的,因为我试过了,我相信你只能使用res.render
一次。),所以在所有的承诺都被执行之后,我真的很想继续在视图中呈现一条新消息。我该怎么做呢?
解决方案
您无法发送多个res.render
. 在标准 HTTP 中,客户端期望接收固定的内容长度,并且您稍后将无法在发送时更改它。
通常,当您想要实现这样的事情时,让您的客户端发送第二个请求,该请求会阻塞,直到服务器真正完成其异步操作。您可以使用 websocket 连接或非常复杂的东西,但这里有一个利用 express 动态使用路由的能力的小示例:
const express = require("express");
const app = express();
let jobs = {};
app.get("/jobs/:number.js", (req, res) => {
const jobNr = req.params.number;
const job = jobs[jobNr];
if (!job) {
console.log("no job found!");
return res.sendStatus(404);
}
job
.then(result => res.send(`document.getElementById("result-${jobNr}").innerHTML = "job ${jobNr} is done with ${result}";`))
.catch(err => res.sendStatus(500))
.then(() => {
// finally clean up, as some client requested this resource
jobs[jobNr] = null;
});
});
app.get("/", (req, res) => {
// set up a job with whatever is necessary to do
const jobNr1 = Math.floor(Math.random() * 10000000);
const job = new Promise(resolve => setTimeout(() => resolve("a result!"), Math.random() * 5000 + 2000));
jobs[jobNr1] = job;
// set up a second job with whatever is necessary to do
const jobNr2 = Math.floor(Math.random() * 10000000);
const job2 = new Promise(resolve => setTimeout(() => resolve("another result!"), Math.random() * 5000 + 2000));
jobs[jobNr2] = job2;
res.send(`<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>test</title>
</head>
<body>
<div id="result-${jobNr1}">job ${jobNr1} running...</div>
<div id="result-${jobNr2}">job ${jobNr2} running...</div>
<script async src="/jobs/${jobNr1}.js"></script>
<script async src="/jobs/${jobNr2}.js"></script>
</body>
</html>
`);
});
app.listen(8080);
推荐阅读
- ssl - ssl 证书 IIS - 自签名
- c++ - protobuf 和 Visual Studio 无缝集成 - 监控 proto 文件更改
- regex - 检查字符串是否包含孤立的单词
- deepsecurity - CLI 开始扫描特定文件
- r - 如何创建一个在 data.frame 中运行良好的新类型?
- java - mybatis如何使用mysql type tinyint处理布尔字段?
- variables - 如何在 Jinja 模板中填充 include_vars 变量?
- wordpress - 付款成功后发送自动消息到实时聊天
- mysql - 使用 MySQL 时启动时 Keycloak 崩溃
- r - 两个线性模型没有不同(F 检验),但回归方程的结果给出了非常不同的值