0

Lately I'm messing around with promises. What I am trying to achieve in the extractMovie() is to loop through all the given urls, parse them, get some date, store it in an array and to resolve that array. But what actually happens is resolving the result (which is an empty array) and then looping through the urls. So actually an empty array is being resolved to the parallel() function. Any ideas on how to achieve that synchronicity in the promise?

const extractMovie = (movieUrl) => {
    return new Promise((resolve, reject) => {
        const fullUrl = mainDomain + movieUrl;
        domParser(fullUrl).then(($) => {
            const titleSelector = '.title h2';
            const ratingSelector = '.user_score_chart';
            const runtimeSelector = '.facts p:nth-child(9)';

            const obj = {
                title: $(titleSelector).html(),
                rating: $(ratingSelector).attr('data-percent'),
                runtime: $(runtimeSelector).text(),
            };
            resolve(obj);
        });
    });
};

const arrayProcessing = async (array) => {
    const results = [];
    for (const entry of array) {
        results.push(await extractMovie(entry));
    }
    return results;
};

const parallel = async (movieUrl1, movieUrl2) => {
    const task1 = arrayProcessing(movieUrl1);
    const task2 = arrayProcessing(movieUrl2);

    return {
        res1: await task1,
        res2: await task2,
    };
};

const run = async () => {
    try {
        const urls = await goInPage();
        await parallel(urls.page1, urls.page2).then((result) => {
            console.log(result);
        });
    } catch (err) {
        console.log(err);
    }
};

run();
  • [This answer](https://stackoverflow.com/a/43766002/157247) to the linked dupetarget question (disclosure: I wrote that answer) shows how to handle dealing with a bunch of promises, in series (which is what I think you want) or in parallel (but I don't think you want that). Pretty much right at the end of the answer. – T.J. Crowder Mar 01 '18 at 13:57
  • I don't think that the questions are dublicates. My issue is realated with not understanding why the array is empty after the forEach. – Alexandar Targov Mar 01 '18 at 14:01
  • That's exactly what the dupetarget addresses. You're logging your array **before** those promises resolve, so nothing has called `result.push` yet. Nothing in your function is waiting for the promises to complete before calling `resolve(result)`. The examples at the end of the answer I linked above are **exactly** applicable, in fact. :-) – T.J. Crowder Mar 01 '18 at 14:13
  • The thing that bugs me is that when iterating the array I am using `forEach`, which is a function. In order to use `await` inside it, the loop has to be defined as `async`. That's where my issue comes. I rewrote my code with a normal `for` loop, but I really do want to use the `forEach` func. I editted my code in the question. – Alexandar Targov Mar 01 '18 at 18:38
  • `forEach` loops through what you give it, synchronously, and calls its callback synchronously. (There are some libraries that offer an async variant of it.) But why do you want to use `forEach`? `for` or `for-of` are usually up to the task... – T.J. Crowder Mar 01 '18 at 19:26
  • Side note: Your `parallel` is basically `Promise.all`, but using named properties instead of array slots... Example `Promise.all` use: `const [res1, res2] = await Promise.all([urls.page1, urls.page2]);`. – T.J. Crowder Mar 01 '18 at 19:28
  • And re `run`: Don't mix `await` and `then`. Use one or the other. Mixing them leads to dramatically confusing code. Your `await parallel(urls.page1, urls.page2).then(result => ...)` should be `const result = await parallel(urls.page1, urls.page2);` (or of course, using `Promise.all`). – T.J. Crowder Mar 01 '18 at 19:29
  • Thanks for the await clarification. About the `forEach` - when working with arrays, usually I use functions such as `.map` `.reduce` `.filter`. That's why I want to use `forEach` in the example so badly. – Alexandar Targov Mar 01 '18 at 20:55

0 Answers0