Как заставить JS дождаться окончания выполнения протокола

У меня есть собственный обработчик протокола 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();
}

Есть идеи, если это возможно?

2 ответа

Решение

Поскольку я не нашел подходящего способа решения своей проблемы с помощью запросов ajax или чего-либо подобного, я наконец-то решил свою проблему, используя своего рода уродливый обходной путь, включающий XmlHttpRequest


Для запуска протокола я все еще использую document.location=cgit:[...]

Я использую систему на стороне сервера, включая "lock-files" - это как общие фиктивные файлы с сгенерированными именами для каждого запроса.

Когда пользователь запрашивает открытие пользовательского протокола, такой файл генерируется на сервере специально для этого одного запроса открытия протокола.

Я создал папку с именем "$locks" на сервере, на котором эти файлы размещаются. После выхода из программы, связанной с протоколом, соответствующий файл удаляется.

Сайт постоянно проверяет, существует ли файл для запроса, используя XmlHttpRequest и запускает обратный вызов, если это не так (пример тайм-аута между тестами: 1 секунда).

Структура новых файлов следующая:

  • lockThisRequest.php: Он создает файл в каталоге $ locks на основе req URL-параметр.
  • 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=$1"

после того, как это закончено.


Как я только что сказал, это работает, но это не просто приятно (поздравляю, если вы следили за этими инструкциями)

Я бы предпочел более простой способ, и (важно) это также может вызвать проблемы с безопасностью lockThisRequest.php а также unlockThisRequest.php файлы!

Я в порядке с этим решением, потому что я использую его только на защищенной паролем личной странице. Но если вы планируете использовать его на общедоступной или незащищенной странице, вы можете захотеть повысить безопасность файлов php.


В любом случае, решение работает для меня сейчас, но если кто-то найдет лучший способ сделать это - например, с помощью запросов ajax - он / она будет очень рад добавить этот путь в соответствующую документацию stackru или тому подобное и опубликовать ссылка на него в этой теме. Я все еще был бы заинтересован в альтернативных решениях:)

Поскольку это не совсем ожидаемое использование window.location, я сомневаюсь, что есть простой способ. Я бы порекомендовал использовать AJAX-запрос и заставить программу C++ отправлять ответ, когда это будет сделано. Таким образом, любой код, который необходимо запустить после программы на С ++, может быть выполнен после завершения запроса.

Другие вопросы по тегам