Как заставить JS дождаться окончания выполнения протокола
У меня есть собственный обработчик протокола 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();
}
Есть идеи, если это возможно?
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++ отправлять ответ, когда это будет сделано. Таким образом, любой код, который необходимо запустить после программы на С ++, может быть выполнен после завершения запроса.