Sean Kelly
Sean Kelly

Reputation: 991

Cannot return axios promise with mongoose

I've been hitting StackOverflow for the last 2 hours and I simply cannot figure out how I'm supposed to retrieve data from an API, store it in Mongo, and then transfer it to my view with express. I feel like I must have made some mistakes in how I'm manipulating the data. I'm relatively new to these concepts and I'd really appreciate some guidance about what the best practices are. I can currently store the information to my DB, but when I try to pass it back up to my route, the axios promise returns undefined. Api keys have been stripped out for this post. Can someone please lend a helping hand?

//pull in express
const express = require('express');
const bodyParser = require('body-parser');
const axios = require('axios');
const mongoose = require('mongoose')

//Connect to mongoDB
mongoose.connect('mongodb://test:[email protected]:39965/companies');
const db = mongoose.connection;

//Create Schema for the application to interact with MongoDB
const companySchema = mongoose.Schema({
    domain:{
        type: String
    },
    email:{
        type: [String]
    },
    confidence: {
        type: [Number]
    },
    create_date:{
        type: Date,
        default: Date.now
    }
}, {collection: 'companies'});

const Company = mongoose.model('Company', companySchema);

//bodyparser middleware for reading form submission
var urlencodedParser = bodyParser.urlencoded({ extended: false });

//declare router as variable for index view
const index   = express.Router();


const hunterKey = '&api_key=8bd4aaded349a5d9784d021c2767e5d23e66140f';
const hunterUrl = `https://api.hunter.io/v2/domain-search?domain=`;

const fullContactKey = `&apiKey=f71cc6c7ccaa28f1`
const fullContactUrl = 'https://api.fullcontact.com/v2/company/lookup?domain=';


function outputHunter(response, res) {
    let comp = response;
    let em = [];
    let c = [];

        for (var i = 0; i < comp.emails.length; i++) {
            //email arrays
            // console.log(comp.emails[i].value);
            em[i] = comp.emails[i].value;
            c[i] = comp.emails[i].confidence;
        }

    var data = new Company({
        domain: comp.domain,
        email: em,
        confidence: c
    });

    //console.log(data);

    var CompanyData = Company(data).save((err, data) => {
        if (err) throw err;
    });

    return data;
}

function searchHunter(searchVal, res) {
    var CompanyData;
    axios.get(hunterUrl + searchVal + hunterKey)
    .then(function (response) {
        response = outputHunter(response.data.data, res);
        CompanyData = response;
    })
    .catch(function (error) {
        console.error(error); throw error;
    });
}

//use declare router for http methods
//get request for index with request, response, next params
index.get('/', function (req, res) {
    //render response  from server using index view from declared path in app.js
    res.render('home', {
        title: "Networkerr home",
        body:
            {
                description: 'The Place to Network',
            }
    });
});

index.get('/:id', (req, res, next) => {
    CompanyData.find()
    .then(function(doc) {
      res.render('company', {company: doc});
    });
});

index.post('/submit', urlencodedParser, (req, res, next) => {
    // console.log(req.body);
    let data = searchHunter(req.body.domain, res);
    console.log('fired')
    console.log(data)
    res.redirect('/' + data._id, {company: data});
});



module.exports = index;

Upvotes: 0

Views: 1549

Answers (1)

Enrique Fueyo
Enrique Fueyo

Reputation: 3488

Some quick fixes: I guess that in index.get('/:id',... you dont need the next parameter as well as in index.post('/submit',... since they are routes, not middlewares.

In the index.get('/:id',..., you need to a) fetch the right route parameter and call the right mongoose method (findById)

index.get('/:id', (req, res) => {
  CompanyData.findById(req.params.id) // <== Specify your id here
  .then((doc) => {
    ..
  });
});

the submit:

Saving the doc in the DB is an asynchronous task (fetch the data from hunter, and save it into the DB)

index.post('/submit', urlencodedParser, (req, res, next) => {
  // console.log(req.body);
  searchHunter(req.body.domain)
  .then(data => {
    // here the Promise is resolved and the doc has been fetched and saved
    console.log('doc fetched and saved');
    console.log(data)
    res.redirect('/' + data._id, {company: data});
  });
  console.log('fired but not fetched and saved');
});

Other modifications will imply that searchHuntermust return a Promise

function searchHunter(searchVal) {
  var CompanyData;
  // return the Promise, so we can know when it has finished
  return axios.get(hunterUrl + searchVal + hunterKey)
  .then(function (response) {
    return outputHunter(response.data.data);
  })
  .catch(function (error) {
    console.error(error); throw error;
  });
}

As well as outputHunter:

function outputHunter(response, res) {
  let comp = response;
  let em = [];
  let c = [];

  for (var i = 0; i < comp.emails.length; i++) {
    //email arrays
    // console.log(comp.emails[i].value);
    em[i] = comp.emails[i].value;
    c[i] = comp.emails[i].confidence;
  }

  var company = new Company({
    domain: comp.domain,
    email: em,
    confidence: c
  });

  // return the Promise so we can know when the company has been saved
  return company.save((err, data) => {
    if (err) throw err;
    return data;
  });

  // shorter, if you dont want to modify data or handle err here
  // return company.save();
}

Upvotes: 1

Related Questions