Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

require not working if not using destructuring assignment

In my nodejs, I have a small mongoose module which exports the model (User). When I require the module without using destructuring assignment and I create the new instance of the model using new operator, I get the error that the model is not a function. But if i use the destructuring assignment when I require the model, everything works fine. Not able to understand why.

User.js exports the model

const mongoose = require('mongoose');

exports.User = mongoose.model('User', {
    email:{
        type: String,
        trim: true,
        minlength: 1,
        reuqired: true
    }
});

Below code throws error if I dont use destructuring operator on line 2:
server.js

const mongoose = require('../DB/mongoose');
const User = require('../Models/User');

console.log(typeof(User));

let user = new User({
    email: "sdfdsf"
});

server.js throws the below error:

let user = new User({
           ^

TypeError: User is not a constructor
    at Object.<anonymous> (F:\javascript\nodePractice\ToDoApp\server\server.js:6:12)
    at Module._compile (internal/modules/cjs/loader.js:678:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:689:10)
    at Module.load (internal/modules/cjs/loader.js:589:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:528:12)
    at Function.Module._load (internal/modules/cjs/loader.js:520:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:719:10)
    at startup (internal/bootstrap/node.js:228:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:576:3)

But If I use a destructuring assignment on line 2, it works all fine. server.js:

const mongoose = require('../DB/mongoose');
const {User} = require('../Models/User');

console.log(typeof(User));

let user = new User({
    email: "sdfdsf"
});
like image 867
kumarmo2 Avatar asked May 27 '18 16:05

kumarmo2


People also ask

Why was object Destructuring used with require?

The object destructuring is a useful JavaScript feature to extract properties from objects and bind them to variables. What's better, object destructuring can extract multiple properties in one statement, can access properties from nested objects, and can set a default value if the property doesn't exist.

How do we assign a default value to a Destructured parameter?

Default values in destructuring assignement only work if the variables either don't exist or their value is set to undefined . Any other value, including null , false and 0 , bypasses the default values in the destructuring statement. You can combine default values with renaming in the destructuring assignment.

What is Destructuring assignment?

The destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables.

How do you swap variables in Destructuring assignment?

[a, b] = [b, a] is the destructuring assignment that swaps the variables a and b . At the first step, on the right side of the destructuring, a temporary array [b, a] (which evaluates to [2, 1] ) is created. Then the destructuring of the temporary array occurs: [a, b] = [2, 1] .


2 Answers

const {User} = require('../Models/User');

is equivalent to

const User = require('../Models/User').User;
//                                    ^^^^^

The module object that require() returns (the exports object that your module filled) does have a .User property. If you don't access that but try to use the module object as a constructor, it throws.

To be explicit, you might want to use

const userModule = require('../Models/User');

console.log(typeof userModule);
console.log(typeof userModule.User);

let user = new userModule.User({
    email: "sdfdsf"
});

Alternatively, if you insist on doing const User = require('../Models/User');, you can also make the constructor function the exported object by overwriting module.exports instead of creating a property on it:

const mongoose = require('mongoose');

module.exports = mongoose.model('User', {
    …
});
like image 120
Bergi Avatar answered Nov 15 '22 20:11

Bergi


You are exporting an object that has a property called "User" that hosts the model. When importing it you need to specify what part of the file you want to import, or you need to later specify what property you want to use. You can still use

const User = require('../Models/User');

But you will need to call User.User, accessing exports.User later on:

let user = new User.User({ //call exports.User from User model file
    email: "sdfdsf"
});
like image 44
Luca Kiebel Avatar answered Nov 15 '22 20:11

Luca Kiebel