Manter uma tela com dados din\u00e2micos atualizados n\u00e3o \u00e9 f\u00e1cil. Uma solu\u00e7\u00e3o \u00e9 empregar XMLHttpRequest<\/a> e ficar fazendo polling<\/a> sobre uma base de tempo regular. Assim perguntar\u00edamos ao servidor se h\u00e1 modifica\u00e7\u00f5es sobre o escopo desejado.<\/p>\n O problema desta aproxima\u00e7\u00e3o \u00e9 que ficamos fazendo um monte de requisi\u00e7\u00f5es ao servidor das quais a maioria \u00e9 apenas para dizer “nenhuma novidade por aqui”<\/p>\n Uma forma contundentemente mais limpa e saud\u00e1vel \u00e9 usar WebSocket<\/a>. YeAPF inclui suporte para WebSocket desde o final de 2016. O problema com eles \u00e9 que voc\u00ea precisa de disponibilizar um porto no seu servidor apenas para ele e utilizar um certificado para poder fazer https em lugar de http com o qual o projeto pode ficar inviabilizado. Insisto, por\u00e9m, em dizer que \u00e9 uma solu\u00e7\u00e3o muit\u00edssimo mais rica e -em certo sentido- potente do que a SSE<\/a>.<\/p>\n Os SSE surgem como uma resposta ao gargalo situacional criado pelo exposto logo acima. Pense neles como um WebSocket simplificado. Ou seja, uma tomada ao qual seu aplicativo se conecta e por meio dela o servidor avisa quando h\u00e1 coisas para serem puxadas. \u00a0Esse aviso gera um evento no cliente que j\u00e1 pode ser o dado a ser puxado ou uma indica\u00e7\u00e3o\u00a0para utilizar outras tecnologias para puxar a informa\u00e7\u00e3o.<\/p>\n N\u00e3o \u00e9 o escopo deste artigo ensinar SSE, mas pode dar uma olhada neste link da W3Schools<\/a>\u00a0e tamb\u00e9m neste outro da MDN<\/a>.<\/p>\n O YeAPF permite a constru\u00e7\u00e3o de aplicativos usando SSE de forma bem simples. Caso o SSE n\u00e3o funcione bem ou n\u00e3o esteja implementado (como no caso de Opera for Linux ou algumas vers\u00f5es de Mozilla for Windows) o YeAPF vai automaticamente cair para uma vers\u00e3o de polling que ao menos permitir\u00e1 continuar com o uso do aplicativo de forma aceit\u00e1vel (\u00e9 claro que n\u00e3o vai ser poss\u00edvel construir um jogo de a\u00e7\u00e3o online fazendo polling mas d\u00e1 para o gasto em aplicativos comerciais)<\/p>\n O exemplo a seguir mostra a utiliza\u00e7\u00e3o do SSE no Javascript. Neste caso trata apenas da ‘recep\u00e7\u00e3o’ dos eventos que s\u00e3o gerados pelo servidor ou pelo pr\u00f3prio SSE.<\/p>\n Com o exemplo anterior, recebemos as mensagens enviadas do servidor. Essas mensagens podem ser disparadas por outros eventos de outros clientes por exemplo ou do pr\u00f3prio servidor, ou na recep\u00e7\u00e3o de um e-mail… enfim a imagina\u00e7\u00e3o do programador \u00e9 o limite.<\/p>\n Para simplificar as coisas, faremos com que o mesmo aplicativo envie certa informa\u00e7\u00e3o ao servidor, o servidor a receba, a manipule e a envie de novo ao cliente que a receber\u00e1 nesse evento ‘marcar’ que acabamos de inventar.<\/p>\n HTML com um botao e uma div para o registro da atividade.<\/p>\n Javascript para cria\u00e7\u00e3o do evento. Repare que estamos usando xMarcar em lugar de marcar para facilitar a leitura durante o aprendizado. Em produ\u00e7\u00e3o deixamos os dois iguais para poder acompanhar melhor.<\/p>\n PHP para a recep\u00e7\u00e3o do evento do lado do servidor.<\/p>\n Bem, se tudo deu certo, seu aplicativo deve mostrar a data do servidor e um contador que vai mudando a cada vez que o bot\u00e3o \u00e9 clicado.<\/p>\n Se isso est\u00e1 funcionando, abra um outro navegador de verdade (todos menos o IE) e veja o que acontece. Abra mais dois ou tr\u00eas. A cada clique do bot\u00e3o em um dos clientes, os outros devem ser informados. H\u00e1 alguns navegadores em que o SSE est\u00e1 mal implementado ou com requisitos superiores. Nesse caso, o gateway n\u00e3o vai ser ‘SSE<\/strong>‘ no evento ‘ready’ e sim ‘Polling<\/strong>‘. Ele mesmo detectar\u00e1 se \u00e9 melhor fazer invoke() ou crave(). Dependendo das necessidades do aplicativo voc\u00ea pode usar isso para impedir que o mesmo seja utilizado nesse navegador.<\/p>\n Se isso lhe fez feliz, coloque num servidor publico distante (se tiver um servidor na \u00c1sia melhor….kkkk)<\/p>\n","protected":false},"excerpt":{"rendered":" Manter uma tela com dados din\u00e2micos atualizados n\u00e3o \u00e9 f\u00e1cil. Uma solu\u00e7\u00e3o \u00e9 empregar XMLHttpRequest e ficar fazendo polling sobre uma base de tempo regular. Assim perguntar\u00edamos ao servidor se h\u00e1 modifica\u00e7\u00f5es sobre o escopo desejado. O problema desta aproxima\u00e7\u00e3o \u00e9 que ficamos fazendo um monte de requisi\u00e7\u00f5es ao servidor das quais a maioria \u00e9 […]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false},"categories":[49,8],"tags":[96,97,98],"jetpack_featured_media_url":"","jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p5O6UV-5b","jetpack-related-posts":[{"id":272,"url":"http:\/\/www.yeapf.com\/wp\/?p=272","url_meta":{"origin":321,"position":0},"title":"Adicionando \u00edcone de espera em aplicativos YeAPF","date":"janeiro 27, 2016","format":false,"excerpt":"A vantagem de usar uma plataforma unificada para suas requisi\u00e7\u00f5es XMLHttpRequest e RESTful \u00e9 que voc\u00ea acaba podendo unificar tamb\u00e9m sua interface com o usu\u00e1rio. Muitas vezes seu servidor demora para responder e um belo \u00edcone de de espera suaviza as coisas com o usu\u00e1rio. Todavia, fazer isso em cada\u2026","rel":"","context":"Em "Desenvolvimento"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":282,"url":"http:\/\/www.yeapf.com\/wp\/?p=282","url_meta":{"origin":321,"position":1},"title":"ChromeApps: Programando para desktop como se fosse web","date":"fevereiro 27, 2016","format":false,"excerpt":"Um aplicativo web on-line tem muitas vantagens e desvantagens - \u00e9 claro - Eu recomendo mesmo assim o desenvolvimento de aplicativos web. Todavia, h\u00e1 uma desvantagem que \u00e9 capaz de cortar o f\u00f4lego: a queda da internet. A internet tem uma caracter\u00edstica not\u00e1vel firmemente alicer\u00e7ada na Lei geral de Murphy\u2026","rel":"","context":"Em "Desenvolvimento"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":184,"url":"http:\/\/www.yeapf.com\/wp\/?p=184","url_meta":{"origin":321,"position":2},"title":"Exemplo - web01 - OnePage YeAPF Web Application","date":"dezembro 26, 2014","format":false,"excerpt":"Esta \u00e9 uma das continua\u00e7\u00f5es deste artigo. Por que criar aplicativos mono p\u00e1gina? Bom, a grande virtude de um aplicativo mono p\u00e1gina \u00e9 que tudo o que voc\u00ea precisar est\u00e1 pronto assim que o usu\u00e1rio carregou a p\u00e1gina inicial e caso sejam necess\u00e1rias mais p\u00e1ginas, formul\u00e1rios, tabelas elas tamb\u00e9m podem\u2026","rel":"","context":"Em "Desenvolvimento"","img":{"alt_text":"","src":"https:\/\/i2.wp.com\/www.yeapf.com\/wp\/wp-content\/uploads\/2019\/05\/office-932926_1920.jpg?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":318,"url":"http:\/\/www.yeapf.com\/wp\/?p=318","url_meta":{"origin":321,"position":3},"title":"Usando btSync para sincronizar e desenvolver em equipe.","date":"novembro 28, 2016","format":false,"excerpt":"Um dos grandes desafios do desenvolvimento grupal \u00e9 manter o c\u00f3digo sincronizado. Concordo, claro, com aqueles que utilizam as ferramentas git\u00a0para poder criar uma vers\u00e3o tempor\u00e1ria (e pessoal) do c\u00f3digo e depois se enganchar de novo com a \u00e1rvore principal. \u00c9 obvio que\u00a0git \u00e9 bem melhor que\u00a0svn por exemplo. Muit\u00edssimo\u2026","rel":"","context":"Em "Desenvolvimento"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":351,"url":"http:\/\/www.yeapf.com\/wp\/?p=351","url_meta":{"origin":321,"position":4},"title":"Abreviando nomes com o YeAPF","date":"abril 21, 2017","format":false,"excerpt":"\u00c0s vezes ao montar uma tabela com dados, \u00e9 necess\u00e1rio cortar a largura das colunas para que toda a informa\u00e7\u00e3o caiba. Todavia, nem sempre isso resolve o problema de mostrar a informa\u00e7\u00e3o de forma consistente. \u00a0Pense no caso de ter varias pessoas com o mesmo nome inicial. Apenas cortar n\u00e3o\u2026","rel":"","context":"Em "Desenvolvimento"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":419,"url":"http:\/\/www.yeapf.com\/wp\/?p=419","url_meta":{"origin":321,"position":5},"title":"Evitando que o waitIcon pisque","date":"junho 22, 2018","format":false,"excerpt":"Esses dias tive que alterar um sistema para mostrar mais dados numa tabela. Como j\u00e1 sabem, n\u00e3o podemos trazer uma tabela inteira para a tela a n\u00e3o ser que ela seja pequena. Com tabelas acima de 30, 50 registros a hist\u00f3ria muda e precisamos segmentar a puxada. Com YeAPF isso\u2026","rel":"","context":"Em "Yet Another PHP Framework"","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"http:\/\/www.yeapf.com\/wp\/index.php?rest_route=\/wp\/v2\/posts\/321"}],"collection":[{"href":"http:\/\/www.yeapf.com\/wp\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.yeapf.com\/wp\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.yeapf.com\/wp\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.yeapf.com\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=321"}],"version-history":[{"count":4,"href":"http:\/\/www.yeapf.com\/wp\/index.php?rest_route=\/wp\/v2\/posts\/321\/revisions"}],"predecessor-version":[{"id":325,"href":"http:\/\/www.yeapf.com\/wp\/index.php?rest_route=\/wp\/v2\/posts\/321\/revisions\/325"}],"wp:attachment":[{"href":"http:\/\/www.yeapf.com\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=321"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.yeapf.com\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=321"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.yeapf.com\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=321"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}Server Side Events<\/h4>\n
Um exemplo<\/h4>\n
\/* inicializo um SSE indicando um grupo de trabalho *\/\r\nmySSE = ycommSSEBase('agenda');\r\n\r\n\/* \r\n adiciono alguns gestores de eventos ao SSE \r\n o evento 'ready' \u00e9 disparado pelo SSE e indica que ele est\u00e1 pronto para funcionar\r\n o evento 'close' \u00e9 disparado pelo SSE e indica o fechamento (correto ou n\u00e3o) do SSE \r\n*\/\r\nmySSE.addEventListener(\r\n \"ready\",\r\n function(e) {\r\n console.log(\"ready: \"+e.gateway);\r\n }\r\n);\r\n\r\nmySSE.addEventListener(\r\n \"close\",\r\n function(e) {\r\n console.log(\"close\");\r\n }\r\n);\r\n\r\n\/* 'marcar' \u00e9 um evento criado pelo programador *\/\r\nmySSE.addEventListener(\r\n \"marcar\",\r\n function(e) {\r\n var dados = JSON.parse(e.data);\r\n console.log(\"dados: \"+e.data);\r\n y$('registro').innerHTML+=e.data;\r\n }\r\n );\r\n\r\n<\/pre>\n<script src='js\/yloader.js'><\/script>\r\n<script src='js\/exemplo_sse.js'><\/script>\r\n<button class=\"button\" id=\"btnMarcar\">Marcar<\/button>\r\n<div id=\"registro\"><\/div><\/pre>\n
\/* js\/exemplo_sse.js *\/ \r\n contador = 0;\r\n enviarEventoMarcar = function(e) {\r\n contador++;\r\n ycomm.invoke(\"meu_gestor\", \"xMarcar\", { c: contador });\r\n }\r\n\r\n addOnLoadManager(\r\n function() {\r\n addEvent('btnMarcar', 'click', enviarEventoMarcar);\r\n \/* inclua aqui o c\u00f3digo de inicializa\u00e7\u00e3o do mySSE \r\n * mostrado no inicio deste exemplo *\/\r\n }\r\n );<\/pre>\n<?php\r\n \/* meu_gestor.php *\/\r\n function qmeu_gestor($a)\r\n {\r\n \/* retorno nulo *\/\r\n $ret='';\r\n\r\n \/* publicamos as vari\u00e1veis passadas como par\u00e2metros no invoke \r\n por exemplo, o 'c' que criamos do lado do cliente no javascript\r\n aparece aqui como uma vari\u00e1vel local *\/\r\n extract(xq_extractValuesFromQuery());\r\n\r\n \/* analisamos o evento de entrada *\/\r\n switch($a)\r\n {\r\n \/* caso se trate do xMarcar ... *\/\r\n case 'xMarcar':\r\n \/* mostrarei a data do servidor *\/\r\n $ts = date('c');\r\n \/* mostrarei um valor aleatorio *\/\r\n $v = random(1000,9999);\r\n \/* empacoto os dados. \r\n 'ts' e 'v' estou criando aqui ao passo que \r\n 'c' veio do javascript *\/\r\n $data = array(\"c\" => $c, \"ts\"=> $ts, \"v\" => $v);\r\n \/* envio para os clientes conectados (todos eles) *\/\r\n SSE::broadcastMessage('marcar', json_encode($data));\r\n \/* indico ao cliente que o envio foi bem sucedido *\/\r\n $ret = array('envio' => 'ok');\r\n break;\r\n }\r\n\r\n \/* retorno normal de um invoke *\/\r\n xq_produceReturnLines($ret, true, 20);\r\n\r\n }\r\n\r\n?>\r\n<\/pre>\n