Necesito abrir una página en una URL, obtener el valor de una variable, formatearla y devolverla.
Tengo este fragmento de código, que funciona:
async function fetchVariable(browser, url) { const page = await browser.newPage(); await page.goto(url); const s = await page.evaluate(async () => Promise.resolve(myVariable)); return s.replace(/\n/g, ''); } Quiero reescribirlo sin await porque... por qué no. Intenté esto:
function fetchVariable(browser, url) { return from(browser.newPage()).pipe( tap(page => page.goto(url)), mergeMap((page) => page.evaluate(async () => Promise.resolve(myVariable))), map((s) => s.replace(/\n/g, '')) ).toPromise(); } Estoy atascado en esta parte: tap(page => page.goto(url)), porque tap no esperará antes de pasar al siguiente operador. Y da como resultado este mensaje de error:
UnhandledPromiseRejectionWarning: Error: el contexto de ejecución se destruyó, muy probablemente debido a una navegación.
Básicamente necesito obtener la page emitida por browser.newPage() , esperar a que page.gotoUrl(url) se complete y reenviar la page al siguiente operador.
Parece que me falta un operador básico pero no puedo ver cuál.
Al ver que el goto devuelve una Promesa, le sugiero que vaya a través de RxJS y convierta todo
function fetchVariable(browser, url) { return from(browser.newPage()).pipe( switchMap(page => // <-- use `switchMap` here from(page.goto(url)).pipe( // <-- inner pipe to allow access to `page` variable switchMap(page => from(page.evaluate)), map(() => myVariable.replace(/\n/g, '')) ) ) ); } Acerca toPromise() : está en desuso y será eliminado por RxJS 8.
Parece que quieres hacer "switchTap". Esencialmente, realice un efecto secundario asíncrono y espere a que se complete antes de continuar.
En lugar de usar tap , podrías hacer switchMap , pero devolver un observable que devuelva la emisión original:
He aquí un ejemplo simplificado de la situación original:
const myObservable$ = of('source #1').pipe( tap(() => myPromiseFn()), switchMap(i => of('source #2')) ); // Order: // - source #1 // - source #2 // - promiseSolución mencionada anteriormente:
const myObservable$ = of('source #1').pipe( switchMap(input => from(myPromiseFn()).pipe( map(() => input) )), switchMap(i => of('source #2')), ); // Order: // - source #1 // - promise // - source #2Aquí hay un pequeño StackBlitz .