如何让JS等到协议执行完成
How to make JS wait until protocol execution finished
我有一个自定义 URL 协议处理程序 cgit:[...]
它启动一个后台进程,在本地机器上配置一些东西。该协议工作正常,我从 JavaScript 启动它(当前使用 document.location = 'cgit:[...]'
),但实际上我希望 JavaScript 等到相关程序退出。
所以基本上我想要 JavaScript 执行的步骤是:
JavaScript 做某事
JavaScript 启动 cgit:[...]
Javascript 等到 cgit:[...]
退出
JavaScript 做点别的事
代码:
function launchCgit(params)
{
showProgressBar();
document.location="cgit:"+params;
document.addEventListener( /* CGit-Program exited event */, hideProgressBar );
}
或:
function launchCgit(params)
{
showProgressBar();
// setLocationAndWait("cgit:"+params);
hideProgressBar();
}
有什么想法可以吗?
因为这不是 window.location 的预期用途,所以我怀疑是否有简单的方法。我的建议是使用 AJAX 请求并让 C++ 程序在完成后发送响应。这样,在 c++ 程序之后需要 运行 的任何代码都可以在请求完成时 运行。
由于我没有找到合适的方法来使用 ajax 请求或任何类似的方法来解决我的问题,我最终使用一种丑陋的解决方法解决了我的问题,包括 XmlHttpRequest
为了启动协议,我仍在使用 document.location=cgit:[...]
我正在使用服务器端系统,包括 "lock-files" - 这就像通用的虚拟文件,每个请求都有生成的名称。
一旦用户请求打开自定义协议,就会在服务器上生成专门针对该协议打开请求的文件。
我在放置这些文件的服务器上创建了一个名为“$locks”的文件夹。一旦与协议相关的程序退出,相应的文件就会被删除。
网站使用 XmlHttpRequest
持续检查请求的文件是否仍然存在,如果不存在则触发回调(测试之间的超时示例:1 秒)。
新文件的结构如下:
lockThisRequest.php
:它根据 req
url 参数在 $locks 目录中创建一个文件。
unlockThisRequest.php
:删除$locks目录下的一个文件;再次基于 req
url 参数。
它的 JavaScript 部分是:
function launchCgit(params,callback)
{
var lock = /* Generate valid filename from params variable */;
// "Lock" that Request (means: telling the server that a request with this ID is now in use)
var locker = new XmlHttpRequest();
locker.open('GET', 'lockThisRequest.php?req='+lock, true)
locker.send(null);
function retry()
{
// Test if the lock-file still exists on the server
var req = new XmlHttpRequest();
req.open('GET', '$locks/'+lock, true);
req.onReadyStateChanged=function()
{
if (req.readyState == 4)
{
if (req.status == 200)
{
// lock-file exists -> cgit has not exited yet
window.setTimeout(retry,1000);
}
else if (req.status == 404)
{
// lock-file not found -> request has been proceeded
callback();
}
}
}
req.send(null);
}
document.location = 'cgit:'+params; // execute custom protocol
retry(); // initialize lockfileCheck-loop
}
用法是:
launchCgit("doThisAndThat",function()
{
alert("ThisAndThat finished.");
});
lockThisRequest.php
-文件:
<?php
file_put_contents("$locks/".$_GET["req"],""); // Create lock file
?>
和unlockThisRequest.php
:
<?php
unlink("../$locks/".$_GET["req"]); // Delete lock file
?>
协议执行的本地程序/脚本可以简单地调用类似:
#!/bin/bash
curl "http://servername/unlockThisRequest.php?req="
完成后。
正如我刚才所说 有效 ,但除此之外别无他法(恭喜你遵守了这些说明)
我更喜欢更简单的方法,(重要) 这也可能导致 lockThisRequest.php
和 unlockThisRequest.php
文件出现安全问题!
我对这个解决方案没问题,因为我只在受密码保护的私人页面上使用它。但是,如果您打算在 public 或不受保护的页面上使用它,您可能需要为 php 文件添加一些安全措施。
无论如何,该解决方案现在对我有用,但如果有人找到更好的方法 - 例如通过使用 ajax 请求 - he/she 非常欢迎将这种方式添加到相应的 Whosebug-documentation 或类似文件,并在此线程上对其进行 post a link。我仍然对替代解决方案感兴趣 :)
我有一个自定义 URL 协议处理程序 cgit:[...]
它启动一个后台进程,在本地机器上配置一些东西。该协议工作正常,我从 JavaScript 启动它(当前使用 document.location = 'cgit:[...]'
),但实际上我希望 JavaScript 等到相关程序退出。
所以基本上我想要 JavaScript 执行的步骤是:
JavaScript 做某事
JavaScript 启动
cgit:[...]
Javascript 等到
cgit:[...]
退出JavaScript 做点别的事
代码:
function launchCgit(params)
{
showProgressBar();
document.location="cgit:"+params;
document.addEventListener( /* CGit-Program exited event */, hideProgressBar );
}
或:
function launchCgit(params)
{
showProgressBar();
// setLocationAndWait("cgit:"+params);
hideProgressBar();
}
有什么想法可以吗?
因为这不是 window.location 的预期用途,所以我怀疑是否有简单的方法。我的建议是使用 AJAX 请求并让 C++ 程序在完成后发送响应。这样,在 c++ 程序之后需要 运行 的任何代码都可以在请求完成时 运行。
由于我没有找到合适的方法来使用 ajax 请求或任何类似的方法来解决我的问题,我最终使用一种丑陋的解决方法解决了我的问题,包括 XmlHttpRequest
为了启动协议,我仍在使用 document.location=cgit:[...]
我正在使用服务器端系统,包括 "lock-files" - 这就像通用的虚拟文件,每个请求都有生成的名称。
一旦用户请求打开自定义协议,就会在服务器上生成专门针对该协议打开请求的文件。
我在放置这些文件的服务器上创建了一个名为“$locks”的文件夹。一旦与协议相关的程序退出,相应的文件就会被删除。
网站使用 XmlHttpRequest
持续检查请求的文件是否仍然存在,如果不存在则触发回调(测试之间的超时示例:1 秒)。
新文件的结构如下:
lockThisRequest.php
:它根据req
url 参数在 $locks 目录中创建一个文件。unlockThisRequest.php
:删除$locks目录下的一个文件;再次基于req
url 参数。
它的 JavaScript 部分是:
function launchCgit(params,callback)
{
var lock = /* Generate valid filename from params variable */;
// "Lock" that Request (means: telling the server that a request with this ID is now in use)
var locker = new XmlHttpRequest();
locker.open('GET', 'lockThisRequest.php?req='+lock, true)
locker.send(null);
function retry()
{
// Test if the lock-file still exists on the server
var req = new XmlHttpRequest();
req.open('GET', '$locks/'+lock, true);
req.onReadyStateChanged=function()
{
if (req.readyState == 4)
{
if (req.status == 200)
{
// lock-file exists -> cgit has not exited yet
window.setTimeout(retry,1000);
}
else if (req.status == 404)
{
// lock-file not found -> request has been proceeded
callback();
}
}
}
req.send(null);
}
document.location = 'cgit:'+params; // execute custom protocol
retry(); // initialize lockfileCheck-loop
}
用法是:
launchCgit("doThisAndThat",function()
{
alert("ThisAndThat finished.");
});
lockThisRequest.php
-文件:
<?php
file_put_contents("$locks/".$_GET["req"],""); // Create lock file
?>
和unlockThisRequest.php
:
<?php
unlink("../$locks/".$_GET["req"]); // Delete lock file
?>
协议执行的本地程序/脚本可以简单地调用类似:
#!/bin/bash
curl "http://servername/unlockThisRequest.php?req="
完成后。
正如我刚才所说 有效 ,但除此之外别无他法(恭喜你遵守了这些说明)
我更喜欢更简单的方法,(重要) 这也可能导致 lockThisRequest.php
和 unlockThisRequest.php
文件出现安全问题!
我对这个解决方案没问题,因为我只在受密码保护的私人页面上使用它。但是,如果您打算在 public 或不受保护的页面上使用它,您可能需要为 php 文件添加一些安全措施。
无论如何,该解决方案现在对我有用,但如果有人找到更好的方法 - 例如通过使用 ajax 请求 - he/she 非常欢迎将这种方式添加到相应的 Whosebug-documentation 或类似文件,并在此线程上对其进行 post a link。我仍然对替代解决方案感兴趣 :)