[ajax] Meerdere responseText binnen 1 call

Pagina: 1
Acties:

  • verytallman
  • Registratie: Augustus 2001
  • Laatst online: 13-11 10:23
Ik heb een php functie die wordt aangeroepen via een HTTP Request, ajax dus.
De php functie die wordt uitgevoerd duurt erg lang (30min of meer) en ik zou graag tussentijds willen zien wat de functie aan het doen is. Het is overigens niet zo dat de functie onverklaarbaar lang bezig is, de functie moet gewoon heel veel doen ;)

Het lijkt echter alsof de "xmlHttpObject.responseText" pas wordt gegeven als de functie helemaal klaar is. Meer requests hebben niet echt zin want er moet maar 1 keer 1 functie worden uitgevoerd.

Als ik de readyState vanuit de php functie zou kunnen beinvloeden zie ik al meer mogelijkheden. Dat kan denk ik niet.

Verwijderd

Start een proces als background thread, laat dat proces lekker zijn ding doen, en poll met een ander script naar de status van het proces. Dat past ook iets meer bij het asynchrone idee van ajax.

Verwijderd

[verwijderd want antwoord klopte totaal niet met de vraag]

[ Voor 93% gewijzigd door Verwijderd op 06-12-2006 22:12 ]


  • verytallman
  • Registratie: Augustus 2001
  • Laatst online: 13-11 10:23
Verwijderd schreef op woensdag 06 december 2006 @ 20:01:
Start een proces als background thread, laat dat proces lekker zijn ding doen, en poll met een ander script naar de status van het proces. Dat past ook iets meer bij het asynchrone idee van ajax.
Bedoel je deze oplossing:
[PHP] exec van shell script - output in page?

  • Cartman!
  • Registratie: April 2000
  • Niet online
Heb misschien n idee voor je :

pagina 1 voert je script uit en update in een session variabele de status.
pagina 2 echo'ed enkel de session var die je continu bijhoud in de 1e pagina

Als je dus elke x seconden een ajax request doet naar pagina 2 heb je de huidige status van je script in pagina 1.

  • SchizoDuckie
  • Registratie: April 2001
  • Laatst online: 18-02 23:12

SchizoDuckie

Kwaak

Cartman! schreef op donderdag 07 december 2006 @ 00:25:
Heb misschien n idee voor je :

pagina 1 voert je script uit en update in een session variabele de status.
pagina 2 echo'ed enkel de session var die je continu bijhoud in de 1e pagina

Als je dus elke x seconden een ajax request doet naar pagina 2 heb je de huidige status van je script in pagina 1.
Helaas werkt dat niet zo 1,2,3 zo in PHP aangezien php (standaard) 'blocking sessions' heeft: Op het moment dat er 1 request nog niet klaar is met z'n actie zal de volgende request gedelayed worden. (Java lost dit op met Threads) Een erg interessant artikel daarover (plus de oplossing) vind je hier

Verder kan je proberen je actie in stapjes uit te voeren: Ik heb zelf bijvoorbeeld vorige week een applicatie geschreven die 22.000 contacten moet aflopen, voor elk contact kijken of er nieuwe artikelen in de database staan, en zo ja ene e-mail versturen naar die contactpersoon.

Hier heb je dus hetzelfde probleem als jij: 22.000 queries uitvoeren duurt even.

De oplossing: stapjes van 100 contactpersonen afwerken en telkens de status updaten en een nieuw request afschieten :)

Stop uploading passwords to Github!


  • verytallman
  • Registratie: Augustus 2001
  • Laatst online: 13-11 10:23
Verwijderd schreef op woensdag 06 december 2006 @ 20:01:
Start een proces als background thread, laat dat proces lekker zijn ding doen, en poll met een ander script naar de status van het proces. Dat past ook iets meer bij het asynchrone idee van ajax.
Dit klinkt als een goede oplossing, ik heb alleen nog niet echt documentatie gevonden die me verder helpt.
Heb je wat links/hints?

  • SKiLLa
  • Registratie: Februari 2002
  • Niet online

SKiLLa

Byte or nibble a bit ?

Het JS HTTP object heeft een .status variabele; als deze 4 is is alle data compleet binnen en kun je dus de responseText uitlezen; echter geeft .status 3 aan dat er al data binnen is (die gewoon middels responseText uit te lezen is), maar nog niet compleet. De batch/chunk oplossing zoals hierboven geadviseerd lijkt me echter ook beter ;)

'Political Correctness is fascism pretending to be good manners.' - George Carlin


  • SchizoDuckie
  • Registratie: April 2001
  • Laatst online: 18-02 23:12

SchizoDuckie

Kwaak

kijk eens naar mijn reply ongeveer 10 centimeter naar boven ;)

Stop uploading passwords to Github!


  • verytallman
  • Registratie: Augustus 2001
  • Laatst online: 13-11 10:23
SKiLLa schreef op donderdag 07 december 2006 @ 16:06:
Het JS HTTP object heeft een .status variabele; als deze 4 is is alle data compleet binnen en kun je dus de responseText uitlezen; echter geeft .status 3 aan dat er al data binnen is (die gewoon middels responseText uit te lezen is), maar nog niet compleet. De batch/chunk oplossing zoals hierboven geadviseerd lijkt me echter ook beter ;)
Status 3 is iets waar ik nog naar kan kijken, thx.

Met de batch/chunk oplossing bedoel je het background process?
Daar zou ik graag meer info over willen vinden. En dan vooral in combinatie hoe je de output tijdens het uitvoeren van de functie kan verkrijgen.

Verwijderd

Ik heb het even gecheckt... het uitlezen van een Session variabele werkt wel delgelijk, je moet alleen wel de sessie afsluiten telkens, zodat de waarde door een ander script kan worden uitgelezen. Bijvoorbeeld (verhoogd een waarde 20 seconden lang met 1)

timer.php
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
$time = time()+20;

while (time() < $time) {
    session_start();
    if(!isset($_SESSION['test'])) {
        $_SESSION['test'] = 1;
    } else {
        $_SESSION['test']++;
    }
    session_write_close();
}
?>


read.php
PHP:
1
2
3
4
5
6
<?php
session_start();
echo "<pre>";
echo $_SESSION['test'];
echo "</pre>";
?>


je kicked dus eerst de ene aan, en zolang die de status 3 heeft (of 2, geen idee eigenlijk), kan je uit die andere dus aflezen wat je wilt, bijvoorbeeld hoeveel % er al verwerkt is, of een verwachte eind tijd, whatever...

edit:

Om de werking ervan goed te zien, moet je ze beiden tegelijkertijd draaien, en de read.php steeds vernieuwen om de nieuwe waarde van de sessie uit te lezen uiteraard ;). ps. Ik wil niet zeggen dat dit een efficiente oplossing is, als je heel veel gegevens verwerkt die een korte verwerkingstijd hebben is dit niet zo zinvol denk ik, beetje veel overhead, daarentegen bij minder loops die heel veel processing time vergen, kan dit de oplossing zijn. Eventueel zou je het aantal keren dat de sessie wordt ge-update kunnen verminderen tot 1:10 of 1:100 afhankelijk van de performance.

[ Voor 26% gewijzigd door Verwijderd op 07-12-2006 16:23 ]


  • verytallman
  • Registratie: Augustus 2001
  • Laatst online: 13-11 10:23
Aangezien het background process niet wil lukken ben ik gaan kloten met de readyState == 3.

JavaScript:
1
2
3
4
5
6
function dispTestie () {
    if (xmlHttp.readyState == 3) {
        document.getElementById("testie_div").innerHTML = xmlHttp.responseText;
        xmlHttp.responseText = null; // <- dit werkt ook niet
    }
}

In een ander stukje js roep ik de onderstaande php functie aan:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function testie () {
        ob_start();
        
        echo ' A ';
        ob_flush();
        flush();
        ob_clean();
        ob_end_clean();
        
        sleep(2);
        
        ob_start();
        
        echo ' B ';
        ob_flush();
        flush();
        ob_clean();
        ob_end_clean();
}

Dit werkt deels. Ik zie eerst een "A" verschijnen , en dan 2 seconden laten zie ik "AB".

Echter, wat ik wil is eerst een "A" , en daarna alleen een "B".

Ik probeer met ob_clean() en ob_end_clean() de output buffer te verwijderen maar dat werkt blijkbaar niet.

Als iemand overigens nog een linkje heeft voor een background thread en daarna pollen met een ander script ben ik ook blij mee :)

  • X-Rey
  • Registratie: April 2002
  • Laatst online: 12-09 21:07
en als je nu iets zou doen als dit, i.p.v alleen echo's te gebruiken:
PHP:
1
2
3
4
5
6
7
8
9
<?php

$var = " A";
echo $var;

$var = " B";
echo $var;

?>

  • verytallman
  • Registratie: Augustus 2001
  • Laatst online: 13-11 10:23
X-Rey schreef op vrijdag 08 december 2006 @ 15:07:
en als je nu iets zou doen als dit, i.p.v alleen echo's te gebruiken:
PHP:
1
2
3
4
5
6
7
8
9
<?php

$var = " A";
echo $var;

$var = " B";
echo $var;

?>
Nee werkt ook niet, maar thx voor je input.

Zelf denk ik nog steeds dat als ik de output buffer kan deleten het goed moet gaan.

  • ATS
  • Registratie: September 2001
  • Laatst online: 28-11 20:56

ATS

Het lijkt me logisch dat je eerst A en dan AB krijgt. Dat komt omdat het resultaat gewoon stapje voor stapje binnenkomt, maar xmlHttp.responseText bevat het hele resultaat. Je kan toch heel eenvoudig bijhouden waar je gebleven was met het verwerken van je resultaat, zodat je de tweede keer die A gewoon negeert en pas op het punt van B begint? Kwestie van wat even de lengte van xmlHttp.responseText opslaan nadat je het resultaat verwerkt hebt, en daarna vanaf dat punt weer verder gaan.

My opinions may have changed, but not the fact that I am right. -- Ashleigh Brilliant


  • verytallman
  • Registratie: Augustus 2001
  • Laatst online: 13-11 10:23
Dat kan opzich wel, maar dat lijkt mij een lelijkere oplossing dan die van een background thread.

Ik ga ermee aan de slag, als iemand nog tips heeft voor een background thread hoor ik het graag.

Edit: ben er nu ff mee bezig, maar 1 nadeel van je oplossing is iig dat de responceText string erorm groot gaat worden. Een half uur lang wordt er namelijk elke seconde weer een nieuwe string aangeplakt, die zelf ook nog best lang is.

[ Voor 37% gewijzigd door verytallman op 08-12-2006 20:31 ]


  • verytallman
  • Registratie: Augustus 2001
  • Laatst online: 13-11 10:23
Omdat ik nogal veel info wil teruggeven ziet het ernaar uit dat de string erg lang gaat worden, zo ongeveer een lengte van 4 miljoen.
Dit komt dus omdat je steeds gegevens toevoegt aan de responceText, die dus de "oude" strings ook bewaart.

Voorbeeld: Je wil steeds 1 getal doorgeven
1ste flush: 1
2ste flush: 1,2
3ste flush: 1,2,3
enz...
Deze string split je dan in javascript en je gebruikt alleen de laatste deel van de array.

Gaat java zo'n grote string aankunnen, ook de client pc?

Het resetten van de reponceText zou wel erg handig zijn als dat kon.

  • SchizoDuckie
  • Registratie: April 2001
  • Laatst online: 18-02 23:12

SchizoDuckie

Kwaak

verytallman schreef op zaterdag 09 december 2006 @ 14:30:
Omdat ik nogal veel info wil teruggeven ziet het ernaar uit dat de string erg lang gaat worden, zo ongeveer een lengte van 4 miljoen.
Dit komt dus omdat je steeds gegevens toevoegt aan de responceText, die dus de "oude" strings ook bewaart.

Voorbeeld: Je wil steeds 1 getal doorgeven
1ste flush: 1
2ste flush: 1,2
3ste flush: 1,2,3
enz...
Deze string split je dan in javascript en je gebruikt alleen de laatste deel van de array.

Gaat java zo'n grote string aankunnen, ook de client pc?

Het resetten van de reponceText zou wel erg handig zijn als dat kon.
Je kan eventueel nog kijken naar Comet volgens mij:

http://www.irishdev.com/NewsArticle.aspx?id=2166

Stop uploading passwords to Github!


  • ATS
  • Registratie: September 2001
  • Laatst online: 28-11 20:56

ATS

Het lijkt me logisch dat je één request ook als één response terug krijgt. Als je dat niet wil, dan moet je gewoon opdelen in blokjes lijkt me en er meerdere requests van maken die je na elkaar stuurt.
Ik zou overigens in jouw voorbeeld niet de hele string steeds splitten en dan alleen het laatste stukje van je array gebruiken, maar echt een pointer bijhouden waar je gebleven was! Dat scheelt heel veel processing.

My opinions may have changed, but not the fact that I am right. -- Ashleigh Brilliant

Pagina: 1