web-dev-qa-db-fra.com

API longue durée d'interrogation

J'ai récemment remarqué que, dans le client js de l'API Heartbeat, il existait une option supplémentaire pour la rapidité des ticks, appelée "interrogation longue" avec un intervalle de 0. Je comprends assez bien ce qu’ils essaient d’atteindre mais je ne comprends pas comment implémenter le plugin avec cette fonctionnalité.

Pour le moment, chaque fois que mon serveur recevait une demande du navigateur, un raccord était déclenché, des données interrogées, une réponse créée et renvoyée au client. Mais avec un intervalle de 0, je devrais attendre que mon événement soit déclenché, puis créer une réponse, non?

Quelqu'un pourrait-il fournir un code simple comme exemple de cette nouvelle fonctionnalité?

5
user3562259

L'API Hearbeat fonctionne en envoyant périodiquement une demande XHR au serveur, avec des points d'ancrage disponibles pour WordPress/plug-ins/themes pour attacher les données à renvoyer au client. Une fois les données renvoyées, un nouveau temps est programmé. La vitesse (ou "impulsion") de la pulsation peut être tempérée, côté serveur ou côté client en réaction à des événements (par exemple, une inactivité de l'utilisateur).

Long sondage

Les sondages longs fonctionnent de manière similaire, mais (source: Wikipedia )

Si le serveur ne dispose d'aucune information pour le client lors de la réception de l'interrogation, au lieu d'envoyer une réponse vide, le serveur maintient la demande ouverte et attend que les informations de réponse soient disponibles. Une fois que cela est fait, le serveur envoie immédiatement une réponse HTTP/S au client, complétant ainsi la requête HTTP/S ouverte.

Ainsi, plutôt que d'envoyer périodiquement des demandes et d'espérer obtenir quelque chose en retour, nous n'en envoyons qu'une seule et le serveur renvoie les données dès qu'elles sont prêtes. Une fois que c'est fait, nous immédiatement initions une nouvelle demande XHR, par conséquent, l'intervalle est 0.

Avertissement de santé

Comme mentionné dans les commentaires de la question, long polling est une fonctionnalité "latente" de WordPress. L'API Heartbeat le prévoit, sans l'implémenter réellement. Les raisons pour lesquelles cela n’a pas été mis en œuvre sont traitées dans track ticket # 23216 , et je vous recommande de lire la discussion.

En bref cependant, les inconvénients/problèmes potentiels incluent:

  • Caching - Les demandes d'interrogation longues chargent WordPress. Les requêtes de base de données (y compris les options, les publications, etc.) sont mises en cache. Si votre script attend que les données soient modifiées, vous devez être conscient du fait que vous ne vérifiez pas les données en cache qui ne changeront pas à moins d'effacer le cache.
  • Paramètres du serveur - Les demandes d'interrogation longues dans ce contexte peuvent être considérées comme une demande de page (potentiellement) très longue. L'exemple ci-dessous se tue après 20 secondes, mais votre hôte peut le tuer bien avant, rendant l'interrogation longue assez impuissante.
  • Ressources du serveur - Chaque visiteur bloquera les ressources du serveur, presque constamment.

Pour ces raisons, je vous recommande de ne l'utiliser que dans un environnement contrôlé (par exemple, vous contrôlez le serveur et les plug-ins/thèmes en cours d'exécution). Mais avec ce niveau de contrôle, vous pouvez envisager d'utiliser plutôt WebSockets.

Mise en place de longues interrogations

1. Réglage de l'intervalle

Vous devez d’abord définir l’intervalle sur "interrogation longue". Effectivement, cela signifie un intervalle de 0.

function wpse162220_heartbeat_settings( $settings ) {
    $settings['interval'] = 'long-polling';
    return $settings;
}
add_filter( 'heartbeat_settings', 'wpse162220_heartbeat_settings' );

2. Ajouter un "écouteur long sondage"

Ceci est un rappel qui vous permet de joindre des données à retourner au client. En reprenant l'exemple de Nacin à partir du billet de piste, nous avons une période de 2 secondes et attendons jusqu'à 20 secondes.

function wpse162220_poll() {

    for ( $i = 0; $i < 10; $i++ ) {

        $val = apply_filters( 'wpse162220_poll', array() );

        if ( ! empty($val) ) {
            echo json_encode($val);
            exit;
        }

        sleep(2);
    }

    echo '0';
    exit;
}

add_action( 'heartbeat_tick', 'wpse162220_poll' );
add_action( 'heartbeat_nopriv_tick', 'wpse162220_poll' ); 

3. (a) Joindre des données

Ceci est une fonction "factice" qui attend juste la troisième itération de la boucle dans la section précédente, puis ajoute des données

function wpse162220_populate_data( $value ){
    static $counter = 0;

    $counter++;

    if( $counter == 3 ){
        $value['wpse162220'] = 'foobar';
    }

    return $value;

}
add_filter( 'wpse162220_poll', 'wpse162220_populate_data' );

3. (b) Afficher les données reçues

J'ai été paresseux ici et ai imprimé le javascript directement à la page. Vous devez normalement passer par tout le rigmarole de l’enregistrement et de la mise en file d’attente d’un fichier javascript.

Tout cela ne fait qu'imprimer la réponse sur la console.

function wpse162220_print_javascript(){
    ?>  
    <script>
    jQuery(document).ready( function($) {
        $(document).on( 'heartbeat-tick.wpse162220', function( event, data ) {
            if ( data.hasOwnProperty( 'wpse162220' ) ) {
                console.log( data );
            }
        });
    });
    </script>
    <?php
}
add_action( 'admin_print_footer_scripts', 'wpse162220_print_javascript', 999 );

Vous devriez le voir imprimer quelque chose comme

 Object {wpse162220: "foobar"} 

à la console toutes les 4 secondes environ.

7
Stephen Harris