Guia de transição de callbacks do JS SDK para Promises

Este guia explica como migrar o código existente do SDK JavaScript da Video API da Vonage, substituindo os manipuladores de conclusão baseados em callback por APIs baseadas em promise.

Visão geral

A partir da versão 2.35.1, o SDK do JavaScript oferece suporte à conclusão baseada em promises nos utilitários do namespace OT e em um amplo conjunto de APIs de Session, Publisher e Subscriber. Isso permite que você:

  • Substitua as chamadas de retorno aninhadas por async / await
  • Tratar erros com o padrão try / catch
  • Organizar os fluxos de publicação e assinatura de forma mais clara
  • Faça a migração de forma incremental, pois as assinaturas das funções de retorno continuam disponíveis para garantir a compatibilidade com versões anteriores

Existem dois padrões de migração:

  • Retorno da promessa direta: Use isso quando o próprio método resolver ou rejeitar uma promessa. Exemplo: const devices = await OT.getDevices()
  • .promise auxiliar: Use isso quando o método antigo ainda retornar Session, Publisher, ou Subscriber, e a API de promessas é disponibilizada no método como um .promise(...) auxiliar. Exemplo: await session.connect.promise(token)

Observação: Os ouvintes de eventos não mudam. Continue usando session.on(...), publisher.on(...), e subscriber.on(...) para eventos assíncronos.

O que mudou

O trabalho de promisificação foi implementado em etapas:

  • Utilitários do namespace OT, como pesquisa de dispositivos, verificações de capacidade de compartilhamento de tela e envio de relatórios de problemas
  • Ciclo de vida da sessão e auxiliares de moderação
  • Session.publish() e Session.subscribe()
  • Estatísticas de editores e APIs de controle de editores
  • Estatísticas de assinantes e APIs de controle de assinantes

Na prática, isso significa que a maior parte do código dos manipuladores de conclusão em um cliente web agora pode ser reescrita usando promessas.

Estratégia de Migração

  1. Converta a função responsável pelo seu fluxo da Video API da Vonage para async.
  2. Substitua os manipuladores de conclusão por await.
  3. Envolva as chamadas de API relacionadas em try/catch.
  4. Mantenha o código orientado a eventos na forma de eventos.
  5. Use o .promise forma quando o método legado ainda retorna um objeto para encadeamento.

Padrão comum de “antes e depois”

Fluxo baseado em callback

const session = OT.initSession(apiKey, sessionId);

session.connect(token, function(connectError) {
  if (connectError) {
    console.error(connectError);
    return;
  }

  const publisher = OT.initPublisher('publisher', publisherOptions, function(publisherError) {
    if (publisherError) {
      console.error(publisherError);
      return;
    }

    session.publish(publisher, function(publishError) {
      if (publishError) {
        console.error(publishError);
      }
    });
  });
});

Fluxo baseado em promessas

async function joinAndPublish() {
	const session = OT.initSession(apiKey, sessionId);

	try {
		await session.connect.promise(token);

		const publisher = await OT.initPublisher.promise('publisher', publisherOptions);

		await session.publish.promise(publisher);
	} catch (error) {
		console.error(error.name, error.message);
	}
}

APIs que retornam diretamente um Promise

Essas APIs podem ser migradas removendo-se o manipulador de conclusão e aguardando-se o resultado diretamente.

Espaço de nomes OT

Estilo de callback Estilo “Promessa”
OT.getDevices(function(error, devices) { ... }) const devices = await OT.getDevices()
OT.checkScreenSharingCapability(function(response) { ... }) const response = await OT.checkScreenSharingCapability()
OT.reportIssue(function(error, issueId) { ... }) const issueId = await OT.reportIssue()

Exemplo:

try {
	const capability = await OT.checkScreenSharingCapability();

	if (!capability.supported) {
		console.warn('Screen sharing is not supported in this browser.');
		return;
	}

	const devices = await OT.getDevices();
	console.log(devices);
} catch (error) {
	console.error(error.name, error.message);
}

APIs de sessão

Estilo de callback Estilo “Promessa”
session.signal(options, function(error) { ... }) await session.signal(options)
session.forceDisconnect(connection, function(error) { ... }) await session.forceDisconnect(connection)
session.forceUnpublish(stream, function(error) { ... }) await session.forceUnpublish(stream)

Os seguintes métodos da Session também retornam promessas diretamente:

  • session.disconnect()
  • session.disableForceMute()
  • session.forceMuteStream(stream)
  • session.forceMuteAll(excludedStreams)
  • session.setEncryptionSecret(secret)
  • session.setIceConfig(iceConfig)

APIs de editores

Estilo de callback Estilo “Promessa”
publisher.getStats(function(error, stats) { ... }) const stats = await publisher.getStats()

Os seguintes métodos do Publisher também retornam promessas diretamente:

  • publisher.publishCaptions(value)
  • publisher.cycleVideo()
  • publisher.setAudioSource(audioSource)
  • publisher.setVideoSource(videoSourceId)
  • publisher.setVideoContentHint(hint)
  • publisher.setPreferredFrameRate(frameRate)
  • publisher.setPreferredResolution(resolution)
  • publisher.setMaxVideoBitrate(bitrateBps)
  • publisher.setVideoBitratePreset(preset)
  • publisher.setVideoMediaProcessorConnector(connector)
  • publisher.setAudioMediaProcessorConnector(connector)

APIs para assinantes

Estilo de callback Estilo “Promessa”
subscriber.getStats(function(error, stats) { ... }) const stats = await subscriber.getStats()

Os seguintes métodos do Subscriber também retornam promessas diretamente:

  • subscriber.subscribeToCaptions(value)
  • subscriber.setPreferredFrameRate(frameRate)
  • subscriber.setPreferredResolution(resolution)
  • subscriber.setCaptionsTranslationLanguage(langCode)
  • subscriber.setVideoMediaProcessorConnector(connector)
  • subscriber.setAudioMediaProcessorConnector(connector)

APIs que utilizam .promise

Alguns métodos mantêm seu valor de retorno original para que o código de encadeamento existente continue funcionando. Use o .promise uma ferramenta útil quando você precisa aguardar a conclusão.

Espaço de nomes OT

Estilo de callback Estilo “Promessa”
OT.initPublisher(targetElement, properties, callback) const publisher = await OT.initPublisher.promise(targetElement, properties)

Auxiliares de sessão

Estilo de callback Estilo “Promessa”
session.connect(token, callback) await session.connect.promise(token)
session.publish(publisher, callback) await session.publish.promise(publisher)
session.publish(targetElement, properties, callback) const publisher = await session.publish.promise(targetElement, properties)
session.subscribe(stream, targetElement, properties, callback) const subscriber = await session.subscribe.promise(stream, targetElement, properties)

Auxiliares de publicação

Estilo de callback Estilo “Promessa”
publisher.publishAudio(value) await publisher.publishAudio.promise(value)
publisher.publishVideo(value, callback) await publisher.publishVideo.promise(value)

Auxiliares de assinantes

Estilo de callback Estilo “Promessa”
subscriber.subscribeToAudio(value) await subscriber.subscribeToAudio.promise(value)
subscriber.subscribeToVideo(value) await subscriber.subscribeToVideo.promise(value)
subscriber.setAudioVolume(value) await subscriber.setAudioVolume.promise(value)
subscriber.restrictFrameRate(value) await subscriber.restrictFrameRate.promise(value)

Exemplo:

try {
	await publisher.publishAudio.promise(false);
	await publisher.publishVideo.promise(true);

	const subscriber = await session.subscribe.promise(stream, 'subscriber', {
		insertMode: 'append',
		width: '100%',
		height: '100%'
	});

	await subscriber.subscribeToAudio.promise(true);
	await subscriber.setAudioVolume.promise(40);
} catch (error) {
	console.error(error.name, error.message);
}

Tratamento de erros

No código baseado em callbacks, os erros são geralmente passados como o primeiro argumento para o manipulador de conclusão. No código baseado em promessas, essas mesmas falhas são apresentadas como promessas rejeitadas.

try {
	const stats = await subscriber.getStats();
	console.log(stats);
} catch (error) {
	console.error(error.name);
	console.error(error.message);
}

Isso facilita o uso de um único try/catch bloco para uma sequência de operações relacionadas.

Adoção gradual

Você não precisa migrar todo o aplicativo de uma só vez. Uma abordagem recomendada é:

  1. Comece com os fluxos de conexão, publicação e assinatura
  2. Em seguida, migrar os auxiliares de moderação e sinalização
  3. Migrar o código de controle do editor e do assinante por último

Como a compatibilidade com callbacks continua em vigor, você pode migrar um caminho de código por vez.

Notas sobre compatibilidade

  • OT.initSession() ainda retorna um Session de forma síncrona.
  • session.unpublish() e session.unsubscribe() continuam sendo auxiliares imediatos na demolição.
  • Ouvintes de eventos, como streamCreated, sessionDisconnected, e videoDisabled continuam sendo baseados em eventos.
  • Se seu aplicativo precisar oferecer suporte a versões mais antigas do SDK, mantenha o formato de callback até que todos os clientes implantados sejam atualizados para uma versão que inclua essas APIs de promise.

Próximos passos