简体   繁体   中英

Requiring a mongoose model from a file which creates the model during a series of promise.then.then chains.

no, you're not my wife, but it sure seems I spend more time with you than her lately.

Anyway, I'm converting a php site to node.js and have gotten the hang of creating mongoose schemas and then models. The only odd part is the fact that you need the model to be able to do any queries on the database.

So I've been var etc = require("./models/etc");'ing my models to be used in my index.js server for app.get requests. I model.find the data I want and pass it to a jade/pug template render.

This has been okay because in all my model files I create the schemas by hand, ie: I write the object, then make a model out of it, and then create documents with those schemas and save them.

But, now I have a product schema/object which relies on fetching products from a shopify api, creating a schema out of that product with a node module generate-schema, then creating the model, then looping through the products from shopify, creating a new document for each and appending some image urls and a couple of other properties and then saving the document.

This all happens in a series of .then(function())'s where an objects object is passed through the entire chain and stores all the variables I need from each function. Then at the end of that promise chain I try to module.exports = objects.variable (in this case it's a mongoose model). But because in index.js when I var product = require('./models/products') it does this asynchronously so the variable product is just {} instead of waiting for the .then promise chain to occur and then use the module.exports which is written at the end.

Is there a way to make require(x) wait for the module.exports to be populated or wait until the whole file has run it's course before assigning the variable?

Thank you.

Here's the code if you need it

var MongoClient = require('mongodb');

// mongodb = MongoClient.connect('mongodb://localhost/myleisure');

var mongoose = require('mongoose');

var fs = require('fs');
var path = require('path');

var generateSchema = require('generate-schema');

// mongoose.connect("mongodb://localhost/myleisure");
//
// var db = mongoose.connection;

var Schema = mongoose.Schema;


var shopify = require('shopify-buy');

var client = shopify.buildClient({
  accessToken: 'private',
  domain: 'my-leisure.myshopify.com',
  appId: 'X'
});




var write = true;

//Only uncomment if you want to export hell
// module.exports = function (callback) {

client.fetchProduct('8461073805').then(function(products) {
  var objects = {};

  objects.schema = generateSchema.mongoose(products.attrs.variants[0]);
  objects.products = products;

  return objects;

})
.then(function(objects){

  var productSchema = new Schema(objects.schema);

  productSchema.add({
    images: {type: [], default: null},
    thumbnail: {type: String, default: "thumb.jpg"},
    name: {type: String, default: "lettini"},
    colour: {type: String, default: null},
    finish: {type: String, default: null},
    size: {type: String, default: null},
    id: {type: String, default: objects.products.attrs.product_id},
    variantId: {type: String, default: null}
  });

  var product = mongoose.model("product", productSchema);


  product.remove({});
  objects.product = product;
  // callback(product)
  return objects;

}).then(function(objects){

  if(write)
    return objects.product.remove({name: "lettini"}).then(function(){

      return objects
    });

}).then(function(objects){
  if(write)
    var productsDir = "./img/products/lettinis/400x";
    var products = objects.products;
    var product = objects.product;
    // console.log(products.variants.length);
    // console.log(i);

    // console.log(schema);
    // console.log(products.attrs.variants);

    fs.readdir(productsDir, (err, skus) => {
      skus.forEach(sku => {
        for (var i = 0; i < products.variants.length - 1; i++) {
          if ( products.variants[i].attrs.variant.sku === sku) {

            var tempProduct = products.variants[i].attrs.variant;
            var newProduct = new product(tempProduct);

            fs.readdir(productsDir + "/" + sku, (err, images) => {
              images.forEach(image => {
                newProduct.colour = tempProduct.option_values[1].value;
                newProduct.frame = tempProduct.option_values[2].value;
                newProduct.size = tempProduct.option_values[0].value;
                newProduct.images.push(image);
              });
              newProduct.save();
            });

          };
        };
      });
    });

    return objects

}).then(function(objects){
  // console.log(objects.product);
  module.exports = objects.product;
});

And in the index.js is simply

var product = require('./models/products');
console.log(product);

output:

{}

Then at the end of that promise chain I try to module.exports = objects.variable (in this case it's a mongoose model). But it does this asynchronously

Don't asynchronously export something. Export the promise instead - immediately:

module.exports = client.fetchProduct(…).then(…)
.…
.then(function(objects){
  // console.log(objects.product);
  return objects.product;
});

So that you can use the promise techniques (also things like Promise.all in case you load more modules) to wait for it in index.js:

require('./models/products').then(function(product) {
  console.log(product);
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM