1

我有一个自定义 URL 协议处理程序cgit:[...]

它启动一个后台进程,在本地机器上配置一些东西。该协议工作正常,我从 JavaScript 启动它(当前使用document.location = 'cgit:[...]'),但我实际上希望 JavaScript 等到相关程序退出。


所以基本上我想要JavaScript做的步骤:

  1. JavaScript 做了一些事情

  2. JavaScript 启动cgit:[...]

  3. Javascript 等到cgit:[...]退出

  4. JavaScript 做其他事情


代码:

function launchCgit(params)
{
    showProgressBar();
    document.location="cgit:"+params;
    document.addEventListener( /* CGit-Program exited event */, hideProgressBar );
}

或者:

function launchCgit(params)
{
    showProgressBar();
    // setLocationAndWait("cgit:"+params);
    hideProgressBar();
}

如果可能的话,有什么想法吗?

4

2 回答 2

1

由于这并不是 window.location 的预期用途,我怀疑是否有一种简单的方法。我的建议是使用 AJAX 请求并让 c++ 程序在完成后发送响应。这样,任何需要在 c++ 程序之后运行的代码都可以在请求完成时运行。

于 2016-08-12T16:36:25.723 回答
1

由于我没有找到合适的方法来使用 ajax 请求或类似的东西来解决我的问题,我最终使用一种丑陋的工作方法解决了我的问题,包括XmlHttpRequest


为了启动我仍在使用的协议document.location=cgit:[...]

我正在使用包括“锁定文件”的服务器端系统 - 这就像通用虚拟文件,为每个请求生成名称。

一旦用户请求打开自定义协议,就会在服务器上专门为该协议打开请求生成这样的文件。

我在放置这些文件的服务器上创建了一个名为“$locks”的文件夹。一旦与协议相关的程序退出,相应的文件就会被删除。

网站不断检查请求的文件是否仍然存在XmlHttpRequest,如果不存在则触发回调(例如测试之间的超时:1 秒)。

新文件的结构如下:

  • lockThisRequest.php: 它根据requrl 参数在 $locks 目录中创建一个文件。
  • unlockThisRequest.php: 它删除 $locks 目录中的一个文件;再次基于requrl 参数。

它的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=$1"

完成后。


正如我刚才所说的那样,这很有效,但它不是很好(恭喜你跟踪这些说明)

我更喜欢更简单的方法,(重要)lockThisRequest.php这也可能导致和文件的安全问题unlockThisRequest.php

我对这个解决方案很好,因为我只在受密码保护的私人页面上使用它。但是如果您打算在公共或非受保护页面上使用它,您可能需要为 php 文件添加一些安全性。


无论如何,该解决方案现在对我有用,但是如果有人找到更好的方法来做到这一点 - 例如通过使用 ajax 请求 - 他/她将非常欢迎将这种方式添加到相应的 stackoverflow-documentation 等并发布在这个线程上链接到它。我仍然对替代解决方案感兴趣:)

于 2016-08-12T17:58:55.570 回答