Guía de transición de las funciones de devolución de llamada del SDK de JS a las «promises»

En esta guía se explica cómo migrar el código existente del SDK de JavaScript de la Video API de Vonage, pasando de los controladores de finalización basados en callbacks a las API basadas en promesas.

Visión general

A partir de la versión 2.35.1, el SDK de JavaScript admite la finalización basada en promesas en las utilidades del espacio de nombres OT y en un amplio conjunto de API de Session, Publisher y Subscriber. Esto te permite:

  • Sustituye las funciones de llamada anidadas por async / await
  • Gestionar los errores con el estándar try / catch
  • Organizar los flujos de publicación y suscripción de forma más clara
  • Realiza la migración de forma incremental, ya que las firmas de las funciones de llamada de retorno siguen estando disponibles para garantizar la compatibilidad con versiones anteriores.

Existen dos patrones migratorios:

  • Devolución por promesa directa: Utilízalo cuando el propio método resuelva o rechace una promesa. Ejemplo: const devices = await OT.getDevices()
  • .promise ayudante: Utilízalo cuando el método antiguo siga devolviendo Session, Publisher, o Subscriber, y la API de «promise» se expone en el método como un .promise(...) ayudante. Ejemplo: await session.connect.promise(token)

Nota: Los oyentes de eventos no cambian. Sigue utilizándolos session.on(...), publisher.on(...)y subscriber.on(...) para eventos asíncronos.

Qué ha cambiado

El trabajo de «promisificación» se llevó a cabo por etapas:

  • Utilidades del espacio de nombres OT, como la búsqueda de dispositivos, la comprobación de la capacidad para compartir pantalla y la notificación de incidencias
  • Ciclo de vida de la sesión y funciones de ayuda para la moderación
  • Session.publish() y Session.subscribe()
  • Estadísticas de editores y API de control de editores
  • Estadísticas de suscriptores y API de gestión de suscriptores

En la práctica, esto significa que ahora se puede reescribir la mayor parte del código de los controladores de finalización de un cliente web utilizando promesas.

Estrategia de migración

  1. Convierte la función que gestiona tu flujo de la Video API de Vonage en async.
  2. Sustituye los controladores de finalización por await.
  3. Envuelve las llamadas a la API relacionadas en try/catch.
  4. Mantén el código basado en eventos en forma de eventos.
  5. Utiliza el .promise forma cuando el método heredado sigue devolviendo un objeto para encadenar.

Patrón habitual de «antes y después»

Flujo basado en callbacks

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);
      }
    });
  });
});

Flujo basado en promesas

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);
	}
}

API que devuelven «Promise» directamente

Estas API se pueden migrar eliminando el controlador de finalización y esperando el resultado directamente.

Espacio de nombres OT

Estilo de devolución de llamada Estilo «Promise»
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()

Ejemplo:

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);
}

API de sesión

Estilo de devolución de llamada Estilo «Promise»
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)

Los siguientes métodos de Session también devuelven promesas directamente:

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

API de editores

Estilo de devolución de llamada Estilo «Promise»
publisher.getStats(function(error, stats) { ... }) const stats = await publisher.getStats()

Los siguientes métodos de Publisher también devuelven promesas directamente:

  • 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)

API para suscriptores

Estilo de devolución de llamada Estilo «Promise»
subscriber.getStats(function(error, stats) { ... }) const stats = await subscriber.getStats()

Los siguientes métodos de Subscriber también devuelven promesas directamente:

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

API que utilizan .promise

Algunos métodos conservan su valor de retorno heredado para que el código de encadenamiento existente siga funcionando. Utiliza el .promise una herramienta útil cuando tengas que esperar a que finalice el proceso.

Espacio de nombres OT

Estilo de devolución de llamada Estilo «Promise»
OT.initPublisher(targetElement, properties, callback) const publisher = await OT.initPublisher.promise(targetElement, properties)

Ayudas de sesión

Estilo de devolución de llamada Estilo «Promise»
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)

Asistentes de edición

Estilo de devolución de llamada Estilo «Promise»
publisher.publishAudio(value) await publisher.publishAudio.promise(value)
publisher.publishVideo(value, callback) await publisher.publishVideo.promise(value)

Asistentes para suscriptores

Estilo de devolución de llamada Estilo «Promise»
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)

Ejemplo:

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);
}

Gestión de errores

En el código basado en callbacks, los errores suelen pasarse como primer argumento al controlador de finalización. En el código basado en promesas, esos mismos errores se muestran como promesas rechazadas.

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

Esto facilita el uso de un único try/catch bloque para una secuencia de operaciones relacionadas.

Adopción gradual

No es necesario migrar toda la aplicación de una sola vez. Un enfoque recomendado es el siguiente:

  1. Empieza con los flujos de conexión, publicación y suscripción
  2. A continuación, migrar las herramientas de moderación y de notificación
  3. Migrar el código de control de emisores y suscriptores en último lugar

Dado que se mantiene la compatibilidad con las funciones de devolución de llamada, puedes migrar una ruta de código cada vez.

Notas sobre compatibilidad

  • OT.initSession() sigue devolviendo un Session de forma sincrónica.
  • session.unpublish() y session.unsubscribe() siguen siendo los principales colaboradores en el desmantelamiento inmediato.
  • Los oyentes de eventos como streamCreated, sessionDisconnectedy videoDisabled siguen basándose en eventos.
  • Si tu aplicación debe ser compatible con versiones anteriores del SDK, mantén el formulario de devolución de llamada hasta que todos los clientes implementados se hayan actualizado a una versión que incluya estas API de promesas.

Próximos pasos

  • Consulta el Referencia sobre sesiones en JavaScript, Referencia del editory Referencia del abonado para obtener información específica sobre cada método.
  • Actualizar las pruebas de la aplicación para que await API basadas en promesas, en lugar de depender de la finalización de las llamadas de retorno.
  • Preferir async Las funciones auxiliares son preferibles a las llamadas de retorno anidadas a la hora de escribir código nuevo.