【问题标题】:Requiring a mongoose model from a file which creates the model during a series of promise.then.then chains.在一系列 promise.then.then 链中创建模型的文件中需要一个 mongoose 模型。
【发布时间】:2017-08-26 05:48:21
【问题描述】:

不,你不是我的妻子,但最近我和你在一起的时间肯定比她多。

无论如何,我正在将一个 php 站点转换为 node.js,并且已经掌握了创建猫鼬模式和模型的窍门。唯一奇怪的是,您需要模型能够对数据库进行任何查询。

所以我一直 var etc = require("./models/etc");'ing 我的模型将在我的 index.js 服务器中用于 app.get 请求。我model.find我想要的数据并将它传递给jade/pug模板渲染。

这没关系,因为在我的所有模型文件中,我都是手动创建模式的,即:我编写对象,然后用它制作模型,然后使用这些模式创建文档并保存它们。

但是,现在我有一个产品模式/对象,它依赖于从 shopify api 获取产品,使用节点模块 generate-schema 从该产品中创建一个模式,然后创建模型,然后遍历来自 shopify 的产品,为每个文件创建一个新文档并附加一些图像 url 和一些其他属性,然后保存文档。

这一切都发生在一系列 .then(function()) 中,其中一个 objects 对象通过整个链传递并存储我需要的每个函数的所有变量。然后在该承诺链的末尾,我尝试使用 module.exports = objects.variable (在这种情况下,它是一个猫鼬模型)。但是因为在 index.js 中,当我 var product = require('./models/products') 它异步执行此操作时,变量 product 只是 {} 而不是等待 .then 承诺链发生然后使用模块。 export 写在最后。

有没有办法让 require(x) 等待 module.exports 被填充或等到整个文件运行正常后再分配变量?

谢谢。

如果你需要,这里是代码

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;
});

而在 index.js 中简直就是

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

输出:

{}

【问题讨论】:

  • 你应该导出promise本身,并使用require('./models/products').then(console.log)
  • @bergi 但是猫鼬模型的目的是在应用程序的整个生命周期中保存,而不仅仅是为了那个承诺线程。
  • 你所说的“那条承诺”是什么意思?承诺值 在应用程序的整个生命周期内存储在模块注册表中。
  • 是的,但是你不会将它用作 require('./models/products').then(x) 你会去 var x = require('./models/products') ;然后稍后在应用程序中转到 x.then(etc..) 对吗?
  • 出现 require(x).then 不是函数?

标签: javascript node.js mongodb mongoose


【解决方案1】:

然后在该承诺链的末尾,我尝试module.exports = objects.variable(在这种情况下,它是一个猫鼬模型)。但它是异步执行的

不要异步导出某些东西。改为导出承诺 - 立即:

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

这样你就可以使用 promise 技术(也可以使用 Promise.all 以防你加载更多模块)在 index.js 中等待它:

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

【讨论】:

  • 但是在应用程序中,我需要在多个位置运行该导出,而不仅仅是在 require('') 之后,而且我宁愿不在我需要使用模块的每个实例中运行 require要么?
  • 导出没有“运行”,它被使用了。是的,你需要在需要模块的任何地方都需要它,但这与它是一个承诺无关。
  • 它保持一个承诺,承诺不会突然将其身份更改为结果值。 then 只是代码始终工作所必需的,即使find 仍在执行。
  • 是否有一个承诺或变量的版本可以将自己设置为具体的类型,例如 var thing = new Promise; var thing = thing.then(function(promise){ return promise});如果你明白我的意思?感谢您的帮助,这正是我所需要的。谢谢
  • 不,你不能 - 这总是意味着你(可能)在值可用之前访问它。就做promise.then(function(thing) { /* your entire module that uses thing */ });
猜你喜欢
  • 2016-01-14
  • 2018-08-25
  • 2012-07-12
  • 1970-01-01
  • 1970-01-01
  • 2015-12-17
  • 2019-01-12
  • 2015-04-12
  • 1970-01-01
相关资源
最近更新 更多