0

I have the below code to access movie sessions from a cinema site. I am looping using a while loop to fetch movie sessions.

And I intend to add the sessions within the loop to array sessionResults which is declared outside the while loop.

R. refers to the Ramda library

let page // passed as an argument to the outer function 

 let sessionResults = [];
  while (currentCinemaIndex < cinemaList.length) {
    await page.goto("www.fakeurl.com");

    const _movies = await movies({ page });

    //Get the sessions for each @_movies
    const _movieSessions = await _movies.map(
      async (_movie, index) => {
       //sessions() returns an array of objects
        const res = (await sessions({ page: page }, index + 1)).map(session => {
          return Object.assign({}, _movie, session);
        });
        return res;
      },
      { page }
    );

//!!! AREA OF CONCERN
    console.log(_movieSessions); // array of promises
    Promise.all(_movieSessions).then(p => {
      sessionResults = R.concat(R.flatten(p), sessionResults);
      // console.log(sessionResults); //  concatenated array 
    });
    console.log(sessionResults); //  [] 
    //while loop logic
    currentCinemaIndex  = //increment currentCinemaIndex  
    limit =// set new limit

If you look at //!!! AREA OF CONCERN I have documented the value of sessionResults at different places.

Could you please advise why the value of sessionResults is not carried through outside Promise.all()?

neo-technoker
  • 369
  • 2
  • 8
  • 26
  • Does `sessionResults` when you assign it *inside the function* have the expected value? Also, does a call of `sessions` return a `Promise`? – CertainPerformance Nov 23 '18 at 00:49
  • *inside the `Promise.all`, that is – CertainPerformance Nov 23 '18 at 00:54
  • `sessions()` returns an array of objects . i have updated the code with that comment. yes `sessionResults` gets the value assigned inside `Promise.all()` Although its a separate question, i dont mind having an implementation without Promise.all() if could change the code in some way.. The only reason I have `Promise.all()` is because `_movieSessions` is an array of Promises – neo-technoker Nov 23 '18 at 01:00
  • 1
    If `sessions` returns an array and not a `Promise`, then you shouldn't `await` it. (similarly, `_movies.map` will also return an array, which isn't a `Promise`, so you shouldn't `await _movies.map` either) – CertainPerformance Nov 23 '18 at 01:01
  • 1
    You're basically trying to use `sessionResults` before it's been populated - either put all the logic that depends on it *inside* the `Promise.all` (or have the `Promise.all` call another function), or use `await Promise.all(...` instead – CertainPerformance Nov 23 '18 at 01:03
  • `await Promise.all()` worked.. thanks – neo-technoker Nov 23 '18 at 01:55
  • 1
    Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – connexo Nov 23 '18 at 03:00

2 Answers2

0

You don't get the updated value of sessionResults because by the time the code executes until the console.log(sessionResults) after Promise.all(...), the promise has not resolved yet.

Therefore, the sessionResults returned by console.log is not yet updated.

What you can do instead is use await like below:

p = await Promise.all(_movieSesions);
sessionResults = R.concat(R.flatten(p), sessionResults);
console.log(sessionResults);

Please note that if you would use await like above, you need to do it inside an async function scope and not the global scope (because it is not async).

yqlim
  • 6,898
  • 3
  • 19
  • 43
  • I don't think so. `_movies` is Array and `sessions()` returns Array, therefore everything after `const _movies = await movies({ page });` is plain simple synchronous treatment of `_movies`. No further async/await is required, nor `Promise.all()`. – Roamer-1888 Nov 23 '18 at 01:26
0

await Promise.all() worked based on comment from @CertainPerformance

Revised code looks like

sessionResults = await Promise.all(_movieSessions).then(p => R.flatten(p));

console.log(sessionResults); //  concatenated array 
neo-technoker
  • 369
  • 2
  • 8
  • 26
  • Yes that will work but from what you say, you don't need to await `sessions()` or await `_movies.map(...)`. All that appears to be synchronous. If I'm right, then you will end up with `const _movieSessions = _movies.map(...)`, and `await Promise.all(_movieSessions).then(p => R.flatten(p))` will simplify to `sessionResults = R.flatten(_movieSessions)`. – Roamer-1888 Nov 23 '18 at 22:00