Newsgroup: it.comp.lang.javascript
Titolo: Ajax e richieste multiple

Salve
sto cercando di sviluppare un'applicazione web che funzioni da
interfaccia di amministrazione per le risorse di una lan.
Questo implica la presenza di "macrooperazioni" ovvero delle operazioni
scomponibili in task piu' semplici, ad esempio la rimozione di un
utente dalla lan comporta (semplificando):
- backup della home directory
- backup della posta
- rimozione dell'utente dal database
E' facile capire che alcune di queste operazioni richiedono molto tempo
(backup, eventuali riavvii di servizi).
Questa applicazione, per come l'ho pensata, genera dinamicamente la
pagina da visualizzare cambiando il contenuto di alcuni div senza il
bisogno di ricaricare completamente la pagina,
una volta che lancio un'operazione, ad esempio la cancellazione di un
utente, piuttosto che eseguire direttamente la richiesta bloccando
quindi la pagina anche per qualche minuto, le microoperazioni vengono
inserite in un database e viene lanciata la funzione execute
execute
- crea una nuova richiesta xmlhhtp
- interroga un pagina php che preleva dal database la prima operazione
nella coda, la esegue, restiruisce il risultato ed elimina l'operazione
dalla coda
- in base alla risposta aggiorna una tabella con la lista delle
operazioni completate oppure visualizza i dettagli dell'errore
con una richiesta asincrona riesco ad ottenere parte di quello che
cerco, ovvero la pagina non si congelata ogni volta che parte
l'esecuzione di un nuovo task.
Il problema e' che ci sono alcune operazioni che vorrei eseguire
durante il completamento dei task,
mi spiego meglio con un esempio, quando parte l'esecuzione del backup
della home l'oggetto xmlhttp e' bloccato per dieci minuti, in quei
dieci minuti voglio cambiare pagina premendo il bottone home che
tramite un'altra richiesta ajax chiama una pagina php che in base ad
aluni parametri passati genera il codice html da visualizzare, questo
pero' non e' possibile neanche se uso due oggetti diversi xmlhttp
perche' la nuova richiesta POST viene messa in coda ed eseguita
soltanto quando quella precedente e' conclusa, ovvero dopo dieci
minuti, almeno cosi' interpreto l'output di firebug
La domanda e' quindi se si possono fare due richieste
"contemporaneamente", o se piuttosto dovrei pensare a qualcosa di
diverso
Saluti

 diverso
La risposta e` "si`". :)
Con lo stesso oggetto xmlHttpRequest puoi fare piu` richieste, basta che
siano asincrone.
Sta a te controllare la risposta del server a quale richiesta si riferisce.
Io mi sono fatto uno scarno framework che accetta dei comandi, li mette in
coda e, una volta al secondo, controlla se ci sono comandi in coda ed
eventualmente fa le richieste via xhr. La risposta contiene il comando da
eseguire (cosi` mi slego dalla richiesta), che puo` anche essere un altro
comando da inserire in coda. In questo modo c'e' un leggero lag (viene
fatta una richiesta al secondo, al massimo), ma mi aiuta a non
sovraccaricare il server. Basta stare attenti a non mandarlo in loop (mi
e` successo... :)
Bye.

 siano asincrone.
Non direi. Con lo stesso oggetto XmlHttpRequest non puoi gestire più
richieste contemporanemente.
Max

Alessandro Pellizzari ha scritto:

il mio problema e' che e' vero che posso lanciare infinite richieste
contemporaneamente, ma le risposte mi arrivano in maniera sequenziale,
la risposta alla seconda richesta arriva sempre dopo la risposta alla
prima, ed e' un problema visto che alcune richieste durano parecchi
minuti.
Provo a risolvere lanciando le operazioni in background anche per il
php, ovvero con un exec("php ... &") lancio il php sulla shell unix che
esegue i task lunghi ed aggiorna il database delle coda quando
l'operazione e' terminata, in questo modo tutte le richieste fatte in
ajax ricevono una risposta in tempi brevissimi.
Quello che non mi piace di questa soluzione e' dover andare a
controllare ogni tot secondi (variabile che posso sempre cambiare caso
per caso) se l'operazione e' stata completata, sarebbe bello avere un
meccanismo tramite il quale sarebbe il server a notificare al client il
cambiamento di qualcosa e non il client a doverlo interrogare
Saluti

Non funziona neanche la soluzione che avevo pensato, allego il codice
di un semplicissimo esempio che spiega benissimo il mio problema.
La pagina presenta una tabella con due campi, in uno e' presente un
form, l'utente scrive un nome, se viene riconosciuto la pagina saluta
l'utente altrimenti mostra un messaggio di errore.
Nell'altro campo viene visualizzato il risultato delle operazioni che
dovrebbero essere eseguite in background
Il problema e' che una volta lanciata la funzione task, il file
execute.php impiega qualche centesimo di secondo per rispondere ma per
l'intera durata dello sleep da 10 secondi la pagina non esegue il
codice che controlla il nome inserito dall'utente
Sapete aiutarmi ?
index.html
____________CODICE_____________
<html>
<head>
<title>Quickstart</title>
<script type="text/javascript" src="funzioni.js"></script>
</head>
<body onload="task()">
<table>
	<tr>
		<td>
				<div id="task">Operazioni completate<br /></div>
		</td>
		<td>
			Scrivimi il tuo nome:
			<input type="text" id="name" onkeypress="processa_nome()" />
			<div id="risposta">Scrivi qualcosa</div>
		</td>
	</tr>
</table>
</body>
</html>
_________FINE__CODICE_______
execute.php
e' il file che viene interrogato ad ogni richiesta ajax, se viene
passato il parametro "nome" controlla se e' presente in un arrai, se
questo parametro non viene passato esegue in background uno sleep di 10
secondi
_____________CODICE_______________
<?php
//xml
header('Content-Type: text/xml');
echo '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>';
echo '<response>';
if (isset($_GET['name'])) {
	$name = $_GET['name'];
	$utenti = array('luca', 'marco', 'fabio', 'gino', 'pino');
	if (in_array($name,$utenti))
		echo 'Eccoti ' . htmlentities($name) . '!';
	else
		echo htmlentities($name) .' non riconosciuto';
} else {
	//manda in backgorund uno scirpt
	exec("php -r 'sleep(10);' &");
	echo "Operazione eseguita correttamente";
}
echo '</response>';
?>
_____________FINE__CODICE_____________
funzioni.js
interroga il file in php ed aggiorna la pagina ad ogni risposta
_____________CODICE_______________
var xmlHttp = createXmlHttpRequestObject();
function processa_nome()
{
	//controlla che l'handler non sia occupato
	if (xmlHttp.readyState == 4 || xmlHttp.readyState == 0)
	{
		//preleva il dato dell'utente
		name = encodeURIComponent(document.getElementById("name").value);
		//chiama la pagina sul server
		xmlHttp.open("GET","execute.php?name=" + name, true);
		//metodo che gestisce la risposta
		xmlHttp.onreadystatechange = show_nome;
		//invia la richiesta
		xmlHttp.send(null);
	}
	else
		setTimeout('processa_nome()', 500);
}
function task()
{
	//controlla che l'handler non sia occupato
	if (xmlHttp.readyState == 4 || xmlHttp.readyState == 0)
	{
		//chiama la pagina sul server
		xmlHttp.open("GET","execute.php", true);
		//metodo che gestisce la risposta
		xmlHttp.onreadystatechange = show_task;
		//invia la richiesta
		xmlHttp.send(null);
	}
	else
		setTimeout('task()', 500);
}
function show_nome()
{
	if (xmlHttp.readyState == 4)
	{
		if (xmlHttp.status == 200)
		{
			//estrai la risposta in xml
			xmlResponse = xmlHttp.responseXML;
			xmlDocumentElement = xmlResponse.documentElement;
			//il testo e' il primo figlio del document element
			message = xmlDocumentElement.firstChild.data;
			//aggiorna la pagina
			document.getElementById("risposta").innerHTML = '<em>' + message +
'</em>';
		}
		else
			alert("Si e' verificato un errore durante la comunicazione: " +
xmlHttp.statusText);
	}
}
function show_task()
{
	if (xmlHttp.readyState == 4)
	{
		if (xmlHttp.status == 200)
		{
			//estrai la risposta in xml
			xmlResponse = xmlHttp.responseXML;
			xmlDocumentElement = xmlResponse.documentElement;
			//il testo e' il primo figlio del document element
			message = xmlDocumentElement.firstChild.data;
			//aggiorna la pagina
			document.getElementById("task").innerHTML += '<em>' + message +
'</em><br />';
			//ricomincia
			setTimeout('task()', 1000);
		}
		else
			alert("Si e' verificato un errore durante la comunicazione: " +
xmlHttp.statusText);
	}
}
function createXmlHttpRequestObject()
{
	var build_xmlHttp;
	try
	{
		//Prova la versione nativa per non IE6
		build_xmlHttp = new XMLHttpRequest();
	}
	catch (e)
	{
		//Non va, ho IE6
		var XmlHttpVersions = new Array('MSXML2.XMLHTTP.6.0',
										'MSXML2.XMLHTTP.5.0',
										'MSXML2.XMLHTTP.4.0',
										'MSXML2.XMLHTTP.3.0',
										'MSXML2.XMLHTTP',
										'Microsoft.XMLHTTP');
		for (var i=0; i<XmlHttpVersions.lenght && !build_xmlHttp; i++)
		{
			try
			{
				build_xmlHttp = new ActiveXObject(XmlHttpVersions[i]);
			}
			catch (e) {}
		}
	}
	if (!build_xmlHttp)
		alert ("Impossibile creare l'handler");
	else
		return build_xmlHttp;
}
__________FINE__CODICE_____________

 }
Non ne capisco il perche' ma se chiamo la funziona in questo modo lo
script funziona come dovrebbe
exec("nice php -r 'sleep (10);' > /dev/null 2>&1 &");
Per ora credo di aver risolto