Search code examples
node.jsasynchronouspromisehapi.jsnightmare

How to return Hapi reply with promise and vo.js


I have an asynchronous nightmare.js process which uses vo.js flow control with a generator:

vo(function *(url) {
  return yield request.get(url);
})('http://lapwinglabs.com', function(err, res) {
  // ... 
})

This needs to return a promise to Hapi (v.13.0.0) with reply() interface. I have seen examples with Bluebird and other promise libraries, eg: How to reply from outside of the hapi.js route handler, but having trouble adapting vo.js. Could someone please provide an example of this?

server.js

server.route({
method: 'GET',
path:'/overview', 
handler: function (request, reply) {
    let crawl = scrape.doCrawl({"user": USERNAME, "pass": PASSWORD});
    reply( ... ).code( 200 );
    }
});

scrape.js

module.exports = {
    DoCrawl: function(credentials) { 
        var Nightmare = require('nightmare');
        var vo = require('vo');

        vo(function *(credentials) {
            var nightmare = Nightmare();
            var result = yield nightmare
               .goto("www.example.com/login")       
               ...
            yield nightmare.end();
            return result

        })(credentials, function(err, res) {
              if (err) return console.log(err);
              return res
        })
    }
};

Solution

  • If you wanted to send the result of doCrawl to hapi's reply method, you'll have to convert doCrawl to return a promise. Something like this (untested):

    server.js

    server.route({
    method: 'GET',
    path:'/overview', 
    handler: function (request, reply) {
        let crawl = scrape.doCrawl({"user": USERNAME, "pass": PASSWORD});
        // crawl is a promise
        reply(crawl).code( 200 );
        }
    });
    

    scrape.js

    module.exports = {
        doCrawl: function(credentials) { 
            var Nightmare = require('nightmare');
            var vo = require('vo');
    
            return new Promise(function(resolve, reject) {
    
                vo(function *(credentials) {
                    var nightmare = Nightmare();
                    var result = yield nightmare
                       .goto("www.example.com/login")       
                       ...
                    yield nightmare.end();
                    return result
    
                })(credentials, function(err, res) {
                    // reject the promise if there is an error
                    if (err) return reject(err);
                    // resolve the promise if successful
                    resolve(res);
                })
            })
        }
    };