1

I'm trying to do a return of JSON object using a Bluebird's Promise.mapSeries/Promise.map within a Promise.mapSeries/Promise.map but I am unable to return them correctly. The function is as follows:

function getMovieDetails(link){
return new Promise(function(resolve, reject) {
    request(link, function(error, response, body){
        var request = Promise.promisifyAll(require("request"), {multiArgs: true});

        var $ = cheerio.load(body);

        var movieYears = "Years";
        var movieYearLinks = [];

        movieYearLinks.each(function(index, item) {
            var movieYear = $(item).text();
            var movieYearLink = $(item).attr("href");
            movieYearLinks.push(movieYearLink);
        });

        Promise.mapSeries(movieYearLinks, function(url) {
            return request.getAsync(url).spread(function(response,body) {
                var $ = cheerio.load(body);
                var movie = {};
                var year = "YEAR".text();

                movie["year"] = year;

                var movieActorsArray = [];
                movieActors.each(function(index, item){
                    var movieActor = $(item).text();
                    movieActorsArray.push(movieActor);
                });
                movie["movieActors"] = movieActorsArray;

                var recommendedMovies = //SOME ROWS;
                var recommendedMoviesLinks = [];

                recommendedMovies.each(function(jndex, jtem){
                    var recommendedRowObject = {};

                    var recommendedText = .text();

                    var recommendedLink = .attr("href");

                    recommendedRowObject["recommendedText"] = recommendedText
                    recommendedRowObject["recommendedLink"] = recommendedLink
                    recommendedMoviesLinks.push(recommendedLink);
                });

                Promise.mapSeries(recommendedMoviesLinks, function(url) {
                    return request.getAsync(url).spread(function(response,body) {
                        var $ = cheerio.load(body);
                        var obj = {};
                        //  GET SOME OTHER DESCRIPTION FROM THE RECOMMENDED MOVIE LINK

                        return obj;
                        });
                }).then(function(results) {
                    // results here returns an array of recommended movie links objects.
                }).catch(function(err) {
                });
                return main;
            });
        }).then(function(results) {
            // results here returns an array of movies

            //  I want to be able to link each movie with its recommended movies.
        }).catch(function(err) {
            console.log("Big Error " + err);
        });
    });
});

}

Some explanation of my code and context.

The home page is a page with movie years. I've looped through them to get the links of the years and put into an array movieYearLinks.

Next, I've used Promise.mapSeries to get some basic info on the movies. Within that basic info, there is are recommended movie link listed in a table. I've looped them through and put them into an array, recommendedMoviesLinks.

After which, I'm going in to grab some other recommended movie (recommendedMovieObject) info before.

I want to create a JSON object with all these info. The JSON object should be something like

{ movieYear: 2017, movieLink: ..., recommendedMovies (This is an array of recommendedMovieObjects): }

I'm open to any solution to achieve this. Thank you in advance.

Gavy
  • 143
  • 2
  • 11
  • 1
    You are not `resolve`-ing the promise you are creating. Also try to clean your flow by un-nesting promises (which is a bad practice). Keep in mind you can link promises one after another by returning something useful. – caisah Mar 03 '17 at 19:00
  • 2
    Add `return` in front of the `Promise.mapSeries()` so it gets linked into the promise chain. – jfriend00 Mar 03 '17 at 19:29
  • First of all, avoid the [`Promise` constructor antipattern](http://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! – Bergi Mar 03 '17 at 23:28
  • What is `main` and why do you `return` it? If you are doing anything asynchronous in a function (and that includes `mapSeries` callback functions), you need to return a *promise* for the result. – Bergi Mar 03 '17 at 23:29

1 Answers1

0

You don't need to nest promises, the whole point of promises is not having to nest callbacks. A new promise need to either be rejected with an error or resolved with a value. Your code should be something like :

let getMovieDetails = function(link){
   return new Promise(function(resolve,reject){
       request(link,function(err,response,body){
         err ? reject(err):resolve(body)
       }
   }).then(function(body){
     // do some cherio stuff
     return dataList
   }).then(function(dataList){
       return Promise.all(dataList.map(function(d){return // a promise of d}) 
   })
}

let finalData = getMovieDetails(link).then(function(data){ 
    //do some computation
}).catch(function(e){ // handle errors })

Depending on your version of node there is no need for bluebird at all. Javascript supports promises.

mpm
  • 20,148
  • 7
  • 50
  • 55
  • 2
    The OP certainly seems to want to nest the two loops at least. The point of promises is not to completely avoid nesting, but to be *able* to get out of nesting at any point. – Bergi Mar 03 '17 at 23:30