Um ouvinte de evento deve ser chamado se estiver anexado depois que o evento já foi acionado? E se o evento for disparado apenas uma vez?
O primeiro exemplo que vem à mente é o ready
evento no jQuery. O seguinte snippet, quando avaliado após o carregamento da página, ainda chamará o retorno de chamada:
$(document).ready(function () {
console.log("Works.");
});
A alternativa para esse comportamento pode ser um sinalizador definido quando a página é carregada, forçando o consumidor da API a verificar se o evento já aconteceu e agir de acordo:
if (document.readyState == "complete") {
console.log("Works.");
} else {
$(document).ready(function () {
console.log("Works.");
});
}
Enquanto o exemplo acima está no contexto de um carregamento de página da Web em que tudo e qualquer coisa (geralmente) precisa acontecer após o carregamento completo da página, os mesmos argumentos podem ser feitos para qualquer componente em um aplicativo que possua eventos "singleton" ( load
, start
, end
, etc.). Um exemplo de um único componente pode ser um mapa com um load
evento acionado para especificar que o mapa foi carregado :
map.on("load", function () {
console.log("The map has loaded.");
});
O exemplo acima vem da API do ArcGIS para JavaScript, onde esse evento é acionado apenas uma vez e, se um consumidor "espera" o carregamento do mapa após o carregamento do mapa, o ouvinte nunca será chamado. O resultado desejado requer a verificação do estado do mapa antes de o ouvinte ser anexado:
if (map.loaded) {
console.log("The map has loaded.");
} else {
map.on("load", function () {
console.log("The map has loaded.");
});
}
Qual comportamento está correto, exigindo que o consumidor verifique se um evento já foi acionado ou sempre chamando o retorno de chamada?
fonte
Subject
vs.ReplaySubject
, onde os eventos dos últimos replays anteriores para assinantes final enquanto o primeiro não. Ou seja, os criadores do Rx modelaram os dois comportamentos, em vez de decidirem um comportamento definido. - E enquanto os links acima vão para a documentação da versão .NET do Rx ', há também um Rx para JavaScript .Respostas:
Isso depende se é realmente uma notificação de evento ou estado (que é o que está pronto). Se for um evento, você não informa o ouvinte sobre todos os eventos anteriores. Se for uma Notificação de Estado, você será avisado imediatamente após a assinatura e você estiver no estado especificado.
A parte complicada será onde pode ser um estado ou um evento, dependendo de como você olha para ela - na pior das hipóteses, isso é explicado pela documentação. Na melhor das hipóteses, você escolhe um bom nome que deixa claro o que você quer dizer.
fonte
load
,start
ouend
o mesmo queready
, como uma notificação de estado?load
não é um evento nem um estado.loadingStarted
é um evento eloading
é um estado.Em geral, não .
Os ouvintes de eventos não devem ser chamados se estiverem anexados após o evento já ter sido acionado. "Você dorme, você perde."
Existem algumas exceções importantes.
$(document).ready()
é talvez o exemplo perfeito - um evento antes do qual todo o contexto da avaliação não é estabelecido de maneira confiável ou completa e serve como um marcador "o processamento completo da função começa aqui".Se, no entanto, você definir a regra de que um manipulador de eventos deve ser acionado, mesmo que seja instalado e / ou ativado após a ocorrência do evento, você declarou que todos os eventos devem ou devem ser armazenados em buffer desde o início até o final da execução do programa, para todo evento concebível. Senão, pode haver manipuladores de eventos estabelecidos em algum evento, em algum lugar no futuro, que você não tenha informações suficientes para saber se deve acionar quando ele estiver estabelecido. Isso significa que você teria que instrumentar todas as fontes de eventos possíveis e armazenar em buffer infinitamente todas elas também. Isso leva o processamento de eventos a partir de uma avaliação lenta (e de todos os seus benefícios de desempenho) até uma avaliação mais ágile para o que estiver no outro extremo do espectro. Avaliação frenética baseada em suposições catastrofizadas sobre quais eventos talvez precisem ser tratados posteriormente?
Os eventos tendem a ser transitórios e numerosos. Definir regras que exigem que cada uma seja armazenada em buffer, sem limitação, na possibilidade de serem eventualmente exploradas - é suicídio por desempenho. Além disso, não há um grande requisito para isso, pois os manipuladores geralmente podem ser estabelecidos no início da vida do programa.
As exceções à regra são casos extremos - cargas de documentos ou subsistemas, por exemplo, que são eventos essenciais, exclusivos e importantes que não são capturáveis ou manipuláveis. Isso é muito próximo aos seus eventos "singleton". Outro grupo que pode precisar de tratamento especial são erros significativos, eventos de segurança ou alterações de status que têm uma necessidade excepcional de serem sinalizados, mesmo que não haja assinantes no sinalizador no momento em que o evento ocorreu.
Uma observação final: um evento "pronto" é sutilmente diferente de um evento "carregado". Embora eles geralmente não sejam claramente distinguidos (por exemplo, HTML
onload
e jQuery são$(document).ready()
considerados logicamente muito semelhantes), e ambos sinalizam a disponibilidade de um recurso ou ambiente de processamento - mas não são exatamente iguais. Carregar (ou terminar) é um evento real - algo sinalizado da infraestrutura para o consumidor. Prontidão, no entanto, é mais o ponto de encontroda infraestrutura carregando o recurso / ambiente e o consumidor se preparando para consumir / tirar proveito dessa disponibilidade. A prontidão vem após o carregamento e é um daqueles eventos / pontos de coordenação especiais designados que devem ser tratados como enfileirados porque você não pode capturá-lo de outra maneira. O fato de haver alguns casos muito especiais, no entanto, não significa que todo evento deva ser acionável a posteriori .fonte