Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

Δημοσ.

Καλησπερα

 

Το σεναριο ειναι : Σε ενα textbox ο χρήστης γράφει και αν υπάρχουν σχετικές λέξεις στη βάση δεδομένων τότε εμφανίζοντε σε ενα dropdown απο κάτω.

 

Για να στείλω τι έγραψε ο χρήστης και να πάρω πισω αποτελέσματα χρησιμοποιώ websockets (node js 0.10.12 και javascript μόνο)

 

Οποτε ο κωδικας ειναι κάπως έτσι

<input id="typename" type="text"  onKeyUp="lookup();" >

function lookup(){
  so.onerror=function (evt) {alert('Error');}

  so.onopen=function(){     
so.send(document.getElementById("typename").value)  
}

 so.onmessage = function (evt) {      
var received_msg = evt.data;      
var packet = JSON.parse(received_msg);      
so.close();        
//βαλε τ αποτελεσματα στο dropdown.....  
}

}

Οπως καταλάβατε υπάρχουν πάρα πολλές συνδέσεις websockets που ανοιγοκλείνουν συνέχεια αν ο χρήστης ψάχνει συνέχεια ή αν πληκτρολογεί γρήγορα.

 

Αν γράψει 4 γράμματα, θα ανοιγοκλείσουν 4 συνδέσεις για να γεμίσει το dropdown αποτελέσματα.  Και ακόμα και αν ο χρήστης επιλέξει αμέσως κατι, οι συνδέσεις θα συνεχίσουν να ανοιγοκλείνουν.

 

Αυτο πρακτικά μεταφράζετε οτι το dropdown "τρεμοπαίζει" και δε σ αφήνει να επιλέξεις κάτι, γιατι γεμίζει συνέχεια ακομα και αν εχεις σταματήσει να πληκτρολογείς.

 

Επισης , αν επιλέξεις κάτι, το επεξεργαστείς και πας να αποθηκεύσεις και ανοιγοκλείνουν απο πίσω ακόμα συνδέσεις, τοτε αργει πολύ να στείλει τα δεδομένα σου να αποθηκευτούν, γιατι περιμένει να κλείσουν όλα.

 

Άρα, μια λυση ειναι κατι τετοιο

<select id="listout" size="5"  onChange="so.close();"  > </select> 

Ο χρήστης επέλεξε κατι απο το dropdown, οπότε κλείστα όλα.

 

Το προβλημα ειναι, ειτε κανω το so global ειτε οχι, οι συνδεσεις ανοίγουν ολες μαζι και δεν κλείνουν εκτος αν πχ, κανω refresh τη σελίδα.

 

Πως μπορω να τις κλεισω ολες, με το που θα γινει καποια επιλογη στο dropdwon?? Καμια ιδεα? Τι κανω λάθος?

 

Σορυ που το περιεγραψα τοσο αναλυτικα, θεωρησα οτι θα σας βοηθησει να το καταλαβετε καλυτερα, η να προτεινετε καποια εναλακτικη

 

Ευχαριστώ προκαταβολικά

Δημοσ.

Υπάρχουν διάφορες βελτιώσεις που θα ήταν καλό να κάνεις.

 

Πρώτον (και ανεξάρτητα αν το κάνεις με ws ή κάπως αλλιώς) δεν είναι καλή ιδέα να στέλνεις query σε κάθε πάτημα πλήκτρου. Είναι πολύ προτιμότερο να το κάνεις "όταν ο χρήστης σταματήσει να πληκτρολογεί". Πώς το καταλαβαίνεις αυτό; Περιμένεις να περάσει ένα μικρό χρονικό διάστημα (ας πούμε 250msec αλλά πειραματίσου) χωρίς δραστηριότητα και μετά στέλνεις το query. Αυτή η συμπεριφορά, δηλαδή το να προγραμματίζεις κάτι να γίνει αλλά να το αναβάλλεις λίγο κάθε φορά που σου ζητάνε να το ξαναπρογραμματίσεις λέγεται debouncing και μπορεί να γίνει κάπως έτσι:

var timeout;

function keyup() {
    if (timeout) {
        clearTimeout(timeout);
    }
    
    timeout = setTimeout(query, 250);
}

function query() {
    // ο κώδικας εδώ εκτελείται μόνο μετά από 250 msec αδράνειας
}

JSFiddle.

 

Αυτό και μόνο θα βελτιώσει πολύ την εμπειρία.

 

Δεύτερον, και πάλι άσχετα από ws ή όχι, όταν κάνεις κάτι τέτοιο χρειάζεσαι response versioning. Αυτό σημαίνει πως από τη στιγμή που στέλνεις ένα query, τυχόν προηγούμενα queries που δεν έχουν απαντηθεί ακόμα είναι πλέον άχρηστα και πρέπει είτε να τα σταματήσεις επιτόπου είτε να αγνοήσεις την απάντηση όταν έρθει (για να δεις τι γίνεται όταν δεν το κάνεις αυτό, βάλε ένα random delay στον server και παίξε). Στην περίπτωσή σου αυτό σημαίνει πως κάθε φορά που στέλνεις query θα βάζεις μέσα και την τρέχουσα τιμή ενός counter που αυξάνεται. Ο server μαζί με τα αποτελέσματα θα επιστρέφει και την τιμή του counter που έστειλες, οπότε όταν δεις μια απάντηση με τιμή διαφορετική της τρέχουσας τιμής του counter ξέρεις πως είναι άχρηστη και πρέπει να την αγνοήσεις.

 

Παράδειγμα:

var counter = 0;
function query() {
    sendData("blah", ++counter);
}

function received(data) {
    if (data.counter != counter) return;
    // do something with data
}

JSFiddle.

 

Αυτές οι δύο τεχνικές μαζί θα κάνουν το autocomplete να δουλεύει smooth as butter που λένε.

 

Τέλος, και ειδικά για ws, δεν είναι σωστή χρήση να ανοίγεις καινούριο socket για κάθε query. Ανοίγεις ένα και το κρατάς ανοιχτό, στέλνοντας όλα τα queries μέσα απο κει. Πότε το κλείνεις τότε; Θα μπορούσες να το αφήνεις απλά συνέχεια ανοιχτό, ή αν είσαι μερακλής να το αφήνεις ανοιχτό "για λίγο" (π.χ. το κλείνεις όταν ο χρήστης κάνει blur το autocomplete control σου).

  • Like 7
Δημοσ. (επεξεργασμένο)

@defacer ευχαριστω για την καταπληκτικη και αναλυτικοτατη απαντηση. Ειχα σκεφτει κ γω να στελνω "όταν ο χρήστης σταματήσει να πληκτρολογεί", αλλα δεν ήξερα πως να ξεχωρίσω πότε σταματάει, και δεν σκέφτηκα καν να χρησιμοποιησω την timeout. Και για τα ws εχεις δικιο οτι δεν πρεπει να μένουν συνεχώς ανοιχτά.

 

Mια τελευταία ερώτηση σχετικά με τα ws.

 

Είναι λογικό νομίζω να ανοίγουν / κλέινουν όταν ο χρήστης κλικάρει στο textbox και όταν κλικάρει κάπου αλλού , αντίστοιχα. Άρα, onFocus και onBlur

 

Οποτε ο κώδικας είναι κάπως ετσι

<input name="title" type="text"  

 

 onFocus=new 

web s0cket(' 

 

ws: / /l0calH0sΤ: 1234');

 

onKeyUp="keyup(); " onBlur="so.close();" >

 

 

 

 

 

 
var so ;  //global
 
function keyup(){
if (timeout) {clearTimeout(timeout);}    
    timeout = setTimeout(lookup, 250);
}
 
function lookup(){
  //κατευθειαν χρηση της global
  so.onopen = function(){
  //συνεχεια του κωδικα μπλα μπλα

 

Κάθε φορά που κλικάρω στο textbox, βλέπω στη κονσολα , "connection accepted" και καθε φορα που κλικαρω καπου αλλου, βλεπω "connection closed normaly" Το θεμα ειναι οτι οσο γραφω, δεν μεταφερει δεδομενα. Δεν βλεπω κανενα αλλο λαθος ουτε στην κονσολα του browser ουτε στη κονσολα των ws.

 

Τι κανω παλι λαθος ?

 

Νομιζω ειναι καλη ιδεα να ανοιγει/κλεινει η συνδεση αναλογα με το τι γινετε στο textbox, αλλα καπου κολλαω παλι

 

Καμια συμβουλη?

 

Ευχαριστω κ παλι

 

PS Δεν μπορω να καταλαβω γιατι δεν μου μαρκαρει τον κωδικα σαν κωδικα το ρημαδι. 20 λεπτα προσπαθω. Μαλλον τραβαει κομπλα οταν βλεπει τη λεξη λοκαλ χοστ?

Επεξ/σία από slevinkelevra
Δημοσ.

Ίσως να έκανες post τον κώδικα κάπου online (π.χ. ένα JSFiddle?) γιατί δε βγαίνει και πολύ νόημα έτσι. Αυτό ας πούμε φαίνεται τελείως λάθος, αλλά δεν δεν ξέρω κατά πόσο φταίει το ο φανταστικός editor των forum:

 

onFocus=new webs0cket('ws: / /l0calH0sΤ: 1234');

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...