0

I do a bulk insert of documents that is initiated by a call to the function, addNewFeedToUserFeeds. addNewFeedToUserFeeds is called from a controller and, I'd like it to return the docs created by the bulk insert function in insertIntoDB, to that controller. However, it seems that because the bulk insert happens inside a promise, the results of that insert are lost. Is there a way to do this that I am missing?

const discover = require('rssdiscovery');
const FeedParser = require('feedparser');
const request = require('request');
const UserFeedEntryMap = require('../models/userFeedEntryMap');

(function () {

  let currentuser = {};

  function insertIntoDB(dataFromFeed) {

    const loop = new Promise((resolve, reject) => {
      const ufmObjects = [];

      dataFromFeed.forEach((item) => {

        const feed = {
          title: item.meta.title,
          description: item.meta.description,
          lastUpdate: item.meta.date, // most recent update
          link: item.meta.link,
          xmlUrl: item.meta.xmlUrl
        };

        const feedEntry = {
          title: item.title,
          link: item.link,
          description: item.description,
          summary: item.summary,
          author: item.author,
          pubdate: item.pubDate,
          date: item.date,
          guid: item.guid,
          image: item.image.url,
          categories: item.categories,
          source: item.source,
        };

        const ufem = new UserFeedEntryMap({
          user_name: currentuser.local.userName,
          feed_entry_metaData: feed,
          feed_entry: feedEntry
        });

        ufmObjects.push(ufem);

      });
      resolve(ufmObjects);
    });

    loop.then((ufmObjects) => {
      UserFeedEntryMap.insertMany(ufmObjects, (error, docs) => {
        if (error) {
          console.log(error);
        } else {
          console.log(docs);
        }
      });
    });
  }

  function parseFeedToObjects(xmlURL) {
    const feedItems = [];
    const req = request(xmlURL);
    const feedparser = new FeedParser();

    req.on('error', (error) => {
      console.log(error);
    });

    req.on('response', function (res) {
      const stream = this;
      if (res.statusCode !== 200) {
        this.emit('error', new Error('Bad status code'));
      } else {
        stream.pipe(feedparser);
      }
    });

    feedparser.on('error', (error) => {
      console.log(error);
    });

    feedparser.on('readable', function () {
      const stream = this;
      const meta = this.meta;
      let item;

      while (item = stream.read()) {
        feedItems.push(item);
      }
    });

    feedparser.on('end', () => {
      // emit error if no items
    //   console.log(feedItems);
      insertIntoDB(feedItems);
    });

  }


  exports.addNewFeedToUserFeeds = function name(user, url) {
    currentuser = user;
    discover(url, (err, results) => {
      const baseURL = url.slice(0, -1);
      parseFeedToObjects(results.links.length > 1 ? results.links[0].href : baseURL + results.links[0].href);
    });
  };
}());
user465001
  • 806
  • 13
  • 29
  • Why is `insertIntoDB` using a Promise at all? Pushing objects into an array isn't asynchronous. The only asynchronous task is `.insertMany()` which doesn't return a Promise but uses a callback. – Andreas Aug 30 '18 at 15:43
  • @Andreas. How would I defer the call to insertMany until all the items were pushed to the array? – user465001 Aug 30 '18 at 15:47
  • @Andreas, I see now. Looks like everything stops until the foreach is completed, like you said. – user465001 Aug 30 '18 at 15:52
  • However, even after removing the promise, I'm still having a problem sending the docs back to the controller. – user465001 Aug 30 '18 at 15:55
  • Thanks @Andreas, I've worked out an answer with you initial comments. I'll post it now. – user465001 Aug 30 '18 at 16:10
  • Why is `loop` even a promise? You don't appear to do anything asynchronous inside that `new Promise` – Bergi Aug 30 '18 at 17:35

1 Answers1

0

You probably want to be using Promise.all() for returning the results of multiple asynchronous processes. It will give you an array of all of the results and will wait until all processes are completed before resolving.

Sean D
  • 134
  • 3