I need to open a page on a URL, get the value of a variable, format it and return it.
I have this piece of code, which works :
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, '');
}
I want to rewrite it without await
because... why not. I tried this :
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();
}
I am stuck on this part : tap(page => page.goto(url)),
because tap
will not wait before passing to the next operator. And it results in this error message :
UnhandledPromiseRejectionWarning: Error: Execution context was destroyed, most likely because of a navigation.
I basically need to get the page
issued by browser.newPage()
, wait for the page.gotoUrl(url)
to complete and forward the page
to the next operator.
It seems that I am lacking a basic operator but I cannot see which one.
CodePudding user response:
Seeing that the goto
return a Promise, I'd suggest you to go all in over RxJS and convert everything
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, ''))
)
)
);
}
About toPromise()
: it's being deprecated and will be removed by RxJS 8.
CodePudding user response:
It sounds like you want to do "switchTap". Essentially perform an async side effect and wait for it to complete before continuing.
Instead of using tap
, you could do switchMap
, but return an observable that returns the original emission:
Here's a simplified example of the original situation:
const myObservable$ = of('source #1').pipe(
tap(() => myPromiseFn()),
switchMap(i => of('source #2'))
);
// Order:
// - source #1
// - source #2
// - promise
Solution mentioned above:
const myObservable$ = of('source #1').pipe(
switchMap(input => from(myPromiseFn()).pipe(
map(() => input)
)),
switchMap(i => of('source #2')),
);
// Order:
// - source #1
// - promise
// - source #2
Here's a little StackBlitz.