2017-07-18 4 views
13

Il existe une fonction dans js qui affiche les messages à la table (les messages sont stockés dans json). Dans Google Chrome, cela fonctionne, mais Safari, Opera ou Microsoft Edge - non! Il y a une erreur dans le code qui est associé à l'appel à setTimeout (callback, 5000) (rien n'est envoyé au rappel). Donc, For (var i = 0; i <respond.length; i ++) ne fonctionnera pas depuis respond === undefined.Pourquoi mon code ne fonctionne pas dans Safari ou Opera?

Mais pourquoi est-ce vrai?

callback(
 
    [{ 
 
     "time": "1500303264", 
 
     "user": "qwe", 
 
     "message": "we", 
 
     "id": 1 
 
    }, 
 
    { 
 
     "time": "1500303987", 
 
     "user": "Max", 
 
     "message": "q", 
 
     "id": 2 
 
    } 
 
    ]); 
 

 
function smile(mess) { 
 
    var smile = ":)"; 
 
    var graficSmile = "<img src = './image/Smile.png' alt='Smile' align='middle'>"; 
 
    var string_with_replaced_smile = mess.replace(smile, graficSmile); 
 

 
    var sad = ":(" 
 
    var graficSad = "<img src = './image/Sad.png' alt='Smile' align='middle'>"; 
 
    var string_with_replaced_smile_and_sad = string_with_replaced_smile.replace(sad, graficSad); 
 

 
    return string_with_replaced_smile_and_sad; 
 
} 
 

 
$.getJSON('data/messages.json', callback); 
 
var exists = []; 
 

 
function callback(respond) { 
 
    var timeNow = Date.now(); 
 

 
    for (var i = 0; i < respond.length; i++) { 
 
    var data = respond[i]; 
 

 
    if (exists.indexOf(data.id) != -1) continue; 
 

 
    var timeInMessage = data.time * 1000; 
 
    var diff_time = (timeNow - timeInMessage); 
 

 
    if (diff_time <= 3600000) { 
 
     var rowClone = $('.mess_hide').clone().removeClass('mess_hide'); 
 

 
     var newDate = new Date(timeInMessage); 
 
     var dateArray = [newDate.getHours(), newDate.getMinutes(), newDate.getSeconds()] 
 
     var res = dateArray.map(function(x) { 
 
     return x < 10 ? "0" + x : x; 
 
     }).join(":"); 
 

 
     $('#messages').append(rowClone); 
 
     $('.time', rowClone).html(res); 
 
     $('.name', rowClone).html(data.user); 
 
     $('.message', rowClone).html(smile(data.message)); 
 
     $('.scroller').scrollTop($('#messages').height()); 
 

 
     exists.push(data.id); 
 
    } 
 
    } 
 
    setTimeout(function(){callback(respond)}, 5000); 
 
}
.scroller { 
 
    width: 490px; 
 
    height: 255px; 
 
    max-height: 255px; 
 
    overflow-y: auto; 
 
    overflow-x: hidden; 
 
} 
 

 
table#messages { 
 
    min-height: 260px; 
 
    width: 100%; 
 
    background: #fffecd; 
 
    border: none; 
 
} 
 

 
table#messages::-webkit-scrollbar { 
 
    width: 1em; 
 
} 
 

 
table#messages::-webkit-scrollbar-track { 
 
    -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); 
 
} 
 

 
table#messages::-webkit-scrollbar-thumb { 
 
    background-color: darkgrey; 
 
    outline: 1px solid slategrey; 
 
} 
 

 
tr { 
 
    height: 20%; 
 
    display: block; 
 
} 
 

 
td.time, 
 
td.name { 
 
    width: 70px; 
 
    max-width: 75px; 
 
    text-align: center; 
 
} 
 

 
td.name { 
 
    font-weight: bold; 
 
} 
 

 
form#text_submit { 
 
    display: inline-flex; 
 
    align-items: flex-start; 
 
} 
 

 
input#text { 
 
    width: 370px; 
 
    height: 30px; 
 
    margin-top: 20px; 
 
    background: #fffecd; 
 
    font-family: 'Montserrat'; 
 
    font-size: 16px; 
 
    border: none; 
 
    align-self: flex-start; 
 
} 
 

 
input#submit { 
 
    padding: 0; 
 
    margin-left: 21px; 
 
    margin-top: 21px; 
 
    height: 30px; 
 
    width: 95px; 
 
    background: #635960; 
 
    border: none; 
 
    color: white; 
 
    font-family: 'Montserrat'; 
 
    font-size: 16px; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div class="scroller"> 
 
    <table id="messages"> 
 
    <tr class="mess_hide"> 
 
     <td class="time"></td> 
 
     <td class="name"></td> 
 
     <td class="message"></td> 
 
    </tr> 
 
    </table> 
 
</div> 
 
<form method="POST" id="easyForm"> 
 
    <input type="text" name="text" id="text"> 
 
    <input type="submit" value="Send" id="submit"> 
 
</form> 
 
</div>

Chrome Chrome

Opera Opera

Répondre

13
  1. Comme on suppose que le var exists - tableau, mais le La valeur du tableau ([]) ne lui est affectée que plus tard, après l'appel $.getJSON(...). Donc, quand callback est appelé pour la première valeur temporelle [] n'est pas réglé pour exists .Nous juste besoin de se déplacer var exists au-dessus du premier appel de callback.
  2. Lorsque callback est appelé par la minuterie, rien ne lui a été transmis. Mais le minuteur doit relire les messages du fichier et les afficher sur l'écran. Donc, à la place setTimeout(function(){callback(respond)}, 5000); nous avons besoin de setTimeout(function(){$.getJSON('data/messages.json', callback);}, 5000);.

var exists = []; 
 
$.getJSON('data/messages.json', callback); 
 

 
function callback(respond) { 
 
    var timeNow = Date.now(); 
 

 
    for (var i = 0; i < respond.length; i++) { 
 
    var data = respond[i]; 
 

 
    if (exists.indexOf(data.id) != -1) continue; 
 

 
    var timeInMessage = data.time * 1000; 
 
    var diff_time = (timeNow - timeInMessage); 
 

 
    if (diff_time <= 3600000) { 
 
     var rowClone = $('.mess_hide').clone().removeClass('mess_hide'); 
 

 
     var newDate = new Date(timeInMessage); 
 
     var dateArray = [newDate.getHours(), newDate.getMinutes(), newDate.getSeconds()] 
 
     var res = dateArray.map(function(x) { 
 
     return x < 10 ? "0" + x : x; 
 
     }).join(":"); 
 

 
     $('#messages').append(rowClone); 
 
     $('.time', rowClone).html(res); 
 
     $('.name', rowClone).html(data.user); 
 
     $('.message', rowClone).html(smile(data.message)); 
 
     $('.scroller').scrollTop($('#messages').height()); 
 

 
     exists.push(data.id); 
 
    } 
 
    } 
 
    setTimeout(function() { 
 
    $.getJSON('data/messages.json', callback); 
 
    }, 5000); 
 
}

+0

Pourriez-vous expliquer votre réponse à ceux qui ne sont pas experts, dites simplement que vous avez ajouté un temps mort et pourquoi. –

+1

@MartinBarker Oui.Look nouvelle réponse. –

5

Depuis callback nécessite un tableau à transmettre comme argument, setTimeout doit veiller à ce que lorsqu'il appelle callback, il p évalue le tableau.

changement

setTimeout(callback, 5000);

à

setTimeout(function(){callback(respond)}, 5000);

qui permet le rappel à appeler avec un argument que le corps d'une fonction anonyme qui sera appelée par setTimeout.

En outre, comme une note de côté, si vous avez utilisé respond.forEach() au lieu d'une boucle de comptage for, le code serait beaucoup plus propre:

respond.forEach(function(data) { 

    if (exists.indexOf(data.id) != -1) continue; 

    var timeInMessage = data.time * 1000; 
    var diff_time = (timeNow - timeInMessage); 

    if (diff_time <= 3600000) { 
     var rowClone = $('.mess_hide').clone().removeClass('mess_hide'); 

     var newDate = new Date(timeInMessage); 
     var dateArray = [newDate.getHours(), newDate.getMinutes(), newDate.getSeconds()] 
     var res = dateArray.map(function(x) { 
     return x < 10 ? "0" + x : x; 
     }).join(":"); 

     $('#messages').append(rowClone); 
     $('.time', rowClone).html(res); 
     $('.name', rowClone).html(data.user); 
     $('.message', rowClone).html(smile(data.message)); 
     $('.scroller').scrollTop($('#messages').height()); 

     exists.push(data.id); 
    } 
    }); 
+0

J'ai présenté vos modifications, mais maintenant le code a arrêté l'affichage des messages du tout. bien que l'erreur ne soit pas là) –

+0

Mais où est la valeur de 'respond' censée provenir? Dans l'état actuel du code dans la question, 'setTimeout()' passe 'respond' mais n'est défini nulle part. (On dirait qu'il est supposé revenir d'un appel '$ .getJSON()', donc je ne suis pas sûr de savoir comment le temps d'attente figure. – Pointy

+0

@Pointy Oui, mais qu'est-ce qui ne va pas si cela n'apparaît pas? –