Javascript 允许在脚本完成运行后单击链接

Javascript 允许在脚本完成运行后单击链接,javascript,html,node.js,express,ejs,Javascript,Html,Node.js,Express,Ejs,我正在试图找到一种方法,允许用户只在特定功能完成运行后单击链接。所以在我的例子中,我有一个ejs模板,其中在图中有两个链接。单击第一个(“运行python”)将激活一个脚本,该脚本需要一些时间才能完成。然后,只有在它完成后(因此有“finished”,它来自以下行:console.log('finished')打印在控制台上)下一个链接(“查看表格”)才是可点击的(或取消标识或类似的内容) 摘要 这应该通过使用AJAX调用来完成。您可以让它返回一些指示作业成功/错误状态的JSON数据,而不是在/

我正在试图找到一种方法,允许用户只在特定功能完成运行后单击链接。所以在我的例子中,我有一个ejs模板,其中在图中有两个链接。单击第一个(“运行python”)将激活一个脚本,该脚本需要一些时间才能完成。然后,只有在它完成后(因此有“finished”,它来自以下行:
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 = []
});