Javascript 允许在脚本完成运行后单击链接
我正在试图找到一种方法,允许用户只在特定功能完成运行后单击链接。所以在我的例子中,我有一个ejs模板,其中在图中有两个链接。单击第一个(“运行python”)将激活一个脚本,该脚本需要一些时间才能完成。然后,只有在它完成后(因此有“finished”,它来自以下行:Javascript 允许在脚本完成运行后单击链接,javascript,html,node.js,express,ejs,Javascript,Html,Node.js,Express,Ejs,我正在试图找到一种方法,允许用户只在特定功能完成运行后单击链接。所以在我的例子中,我有一个ejs模板,其中在图中有两个链接。单击第一个(“运行python”)将激活一个脚本,该脚本需要一些时间才能完成。然后,只有在它完成后(因此有“finished”,它来自以下行:console.log('finished')打印在控制台上)下一个链接(“查看表格”)才是可点击的(或取消标识或类似的内容) 摘要 这应该通过使用AJAX调用来完成。您可以让它返回一些指示作业成功/错误状态的JSON数据,而不是在/
console.log('finished'
)打印在控制台上)下一个链接(“查看表格”)才是可点击的(或取消标识或类似的内容)
摘要 这应该通过使用AJAX调用来完成。您可以让它返回一些指示作业成功/错误状态的JSON数据,而不是在
/run
中使用重定向
单击runpython
,它将运行AJAX调用,而不是将页面重定向到/
在AJAX调用的OnSuccess
上,可以启用查看表
代码
HTML
NodeJs
app.get("/run", function(req, res) {
...
// res.redirect('/');
res.json({ success: true });
});
正如emil在回答中所建议的那样,您可能可以使用ajax来实现, 但是既然您使用的是ejs模板引擎,为什么不使用它呢?
(您只需将
.html
模板文件扩展名更改为.ejs
)
另外,我认为您最好的选择是不要使用res.redirect
最好使用
res.render
并向视图传递一个参数,默认设置为false
一个基本的例子:
server.js
// ...
app.get("/", function (req, res) {
res.render("search", { active: false });
})
// ...
app.get("/run", function (req, res) {
// ...
pyshell.end(function (err) {
if (err) throw err;
console.log('finished');
res.render("search", { active: true });
});
});
search.ejs
<p><a href="/run">Run python</a></p>
<p>
<%if (active) { %>
<a href="/data">See the table</a>
<% } else { %>
See the table
<% } %>
</p>
看到桌子了吗
现在,只有在python脚本完成时,
查看表
链接才可单击。U可以使用阻止函数Jquery来阻止链接
$("a").click(function() {
if (status == "1") {
return true;
} else {
return false;
e.preventDefault();
}
});
这是我用来阻止用户在不运行函数的情况下导航到其他页面的函数
我初始化了一个名为status的变量,其值为0
然后,一旦函数成功,我就增加变量
因此,如果状态为0,则URL将不起作用,完成函数后,状态将增加到1,因此如果条件为true,则返回true语句。如果不是,它将返回错误语句,并将使用e.preventDefault()阻止它。为什么不试试socket.io? 这里是简化的代码,但功能齐全 (注意:“msg”对象仅为示例,以供进一步使用) index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Title</title>
</head>
<body>
<h1>Search for a movie</h1>
<p><a href="#" onclick="runPython()"> Run python </a></p>
<p><a id="table-data"> See the table </a></p>
<script src="/socket.io/socket.io.js"></script>
<script>
var msg = {
msg: "TestMsgSend",
iParam: 100,
sParam: "Test Param 1",
aParam: [1, 2, 3]
}
var socket = io();
socket.on("server:finished", function (msg) {
// msg = "TestMsgReceived", for further usage
console.log("\nId: " + socket.id + "\nmsg: " + msg.msg + "\niParam: " + msg.iParam + "\nsParam: " + msg.sParam + "\naParam: " + msg.aParam);
document.getElementById("table-data").setAttribute("href", "/data");
});
function runPython() {
socket.emit("client:run", msg);
}
</script>
</body>
</html>
package.json
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.16.2",
"socket.io": "^2.0.4"
}
}
从node app.js开始,享受为什么不做一些简单的保护变量呢?在代码中:
var ready = false; // 1) the guard
app.get('/data', function(req, res) {
if (ready) { // 2) view execution blocked until guard is ready
res.render(__dirname + '/well.html');
}
});
app.get("/run", function(req, res) {
var pyshell = new PythonShell('script2.py');
pyshell.send(JSON.stringify(thelist))
pyshell.on('message', function (message) {
// received a message sent from the Python script (a simple "print" statement)
jsondata += message
});
// end the input stream and allow the process to exit
pyshell.end(function (err) {
if (err) {
throw err;
};
ready = true; // 3) if evetything is OK the guard is now ready
console.log('finished');
});
res.redirect('/')
thelist = []
});
我在你发布的时候尝试过这个,在我点击RunPython之后,“查看表格”已经可以点击了,但是脚本还没有完成。为什么会这样?换句话说,它应该在app.get中的整个代码运行之后发送res.json({success:true}),因此console.log被执行。当然可以
res.json
应该在app.get完成所有工作后调用,这意味着它应该在承诺链的末尾或最后一次回调中被激发。但这就是我现在正在做的。我在console.log('finished')行下面插入了res.json。但是,它仍然在console.log打印之前运行。如果删除res.redirect('/')
on run函数?假设您最初隐藏(或禁用)该链接(“查看表”),然后在console.log('finished')
之后的pyshell.end
函数中向其添加一个内联样式,这样做有效吗?e、 g:var linkToEnable=document.querySelector(“.link to enable”);linkToEnable.style.display=“block”
(只是一个示例-这里的要点是确定是否可以在指定的时刻添加内联样式:在相关函数完成后)嗯,我不确定我做得是否正确,但我得到一个错误,文档没有定义。这是服务器端的node.js代码,它似乎不允许dom操作。1-对单线程服务器使用全局变量永远不会正确地处理多个用户。2-这并不能回答禁用链接的问题。为此实现套接字用例是多余的。你不是在制作一个实时应用程序。它只是在禁用一个链接!这是问题的简单部分。但是它如何设置状态的另一部分;)?你必须在成功完成功能后增加状态值,你介意将这部分代码添加到你的解决方案中吗?
$("a").click(function() {
if (status == "1") {
return true;
} else {
return false;
e.preventDefault();
}
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Title</title>
</head>
<body>
<h1>Search for a movie</h1>
<p><a href="#" onclick="runPython()"> Run python </a></p>
<p><a id="table-data"> See the table </a></p>
<script src="/socket.io/socket.io.js"></script>
<script>
var msg = {
msg: "TestMsgSend",
iParam: 100,
sParam: "Test Param 1",
aParam: [1, 2, 3]
}
var socket = io();
socket.on("server:finished", function (msg) {
// msg = "TestMsgReceived", for further usage
console.log("\nId: " + socket.id + "\nmsg: " + msg.msg + "\niParam: " + msg.iParam + "\nsParam: " + msg.sParam + "\naParam: " + msg.aParam);
document.getElementById("table-data").setAttribute("href", "/data");
});
function runPython() {
socket.emit("client:run", msg);
}
</script>
</body>
</html>
var express = require("express");
var app = express();
var http = require("http").Server(app);
var io = require("socket.io")(http);
app.use("/", express.static(__dirname + "/"));
// ***************************************************************************
// ***************************************************************************
// ***** Your code
// ***************************************************************************
// ***************************************************************************
io.on("connection", function (socket) {
console.log("New connection with id: " + socket.id);
socket.on("client:run", function (msg) {
// msg = "TestMsgSend", for further usage
console.log("\nId: " + socket.id + "\nmsg: " + msg.msg + "\niParam: " + msg.iParam + "\nsParam: " + msg.sParam + "\naParam: " + msg.aParam);
// ***************************************************************************
// ***************************************************************************
// ***** Your code
// ***************************************************************************
// ***************************************************************************
msg.msg = "TestMsgReceived";
msg.iParam++;
msg.sParam = "Test Param 2";
msg.aParam.push(4, 5, 6)
io.emit("server:finished", msg);
});
});
// ***************************************************************************
// ***************************************************************************
// ***** Your code
// ***************************************************************************
// ***************************************************************************
http.listen(80, function () {
console.log("listening on *:80");
});
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.16.2",
"socket.io": "^2.0.4"
}
}
var ready = false; // 1) the guard
app.get('/data', function(req, res) {
if (ready) { // 2) view execution blocked until guard is ready
res.render(__dirname + '/well.html');
}
});
app.get("/run", function(req, res) {
var pyshell = new PythonShell('script2.py');
pyshell.send(JSON.stringify(thelist))
pyshell.on('message', function (message) {
// received a message sent from the Python script (a simple "print" statement)
jsondata += message
});
// end the input stream and allow the process to exit
pyshell.end(function (err) {
if (err) {
throw err;
};
ready = true; // 3) if evetything is OK the guard is now ready
console.log('finished');
});
res.redirect('/')
thelist = []
});