Trouble to destroy a model with Sequelize - javascript

What is happening?
I am trying to destroy one model via params. But when I try to destroy, it appears this error at the console.
(node:13350) UnhandledPromiseRejectionWarning: TypeError: results.map is not a function
at Query.handleSelectQuery (/home/vagnerwentz/Documents/freelance/autoparanaiba-api/node_modules/sequelize/lib/dialects/abstract/query.js:261:24)
at Query.formatResults (/home/vagnerwentz/Documents/freelance/autoparanaiba-api/node_modules/sequelize/lib/dialects/mysql/query.js:118:19)
at /home/vagnerwentz/Documents/freelance/autoparanaiba-api/node_modules/sequelize/lib/dialects/mysql/query.js:71:29
at tryCatcher (/home/vagnerwentz/Documents/freelance/autoparanaiba-api/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/home/vagnerwentz/Documents/freelance/autoparanaiba-api/node_modules/bluebird/js/release/promise.js:547:31)
at Promise._settlePromise (/home/vagnerwentz/Documents/freelance/autoparanaiba-api/node_modules/bluebird/js/release/promise.js:604:18)
at Promise._settlePromise0 (/home/vagnerwentz/Documents/freelance/autoparanaiba-api/node_modules/bluebird/js/release/promise.js:649:10)
at Promise._settlePromises (/home/vagnerwentz/Documents/freelance/autoparanaiba-api/node_modules/bluebird/js/release/promise.js:729:18)
at _drainQueueStep (/home/vagnerwentz/Documents/freelance/autoparanaiba-api/node_modules/bluebird/js/release/async.js:93:12)
at _drainQueue (/home/vagnerwentz/Documents/freelance/autoparanaiba-api/node_modules/bluebird/js/release/async.js:86:9)
at Async._drainQueues (/home/vagnerwentz/Documents/freelance/autoparanaiba-api/node_modules/bluebird/js/release/async.js:102:5)
at Immediate.Async.drainQueues [as _onImmediate] (/home/vagnerwentz/Documents/freelance/autoparanaiba-api/node_modules/bluebird/js/release/async.js:15:14)
at processImmediate (internal/timers.js:439:21)
at process.topLevelDomainCallback (domain.js:130:23)
(node:13350) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:13350) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
The route that call the function
router.delete('/agricultural/announce/:id', passport.authenticate(), (req, res) => {
AnnouncementAgricultural.destroy(req, res);
})
The function
exports.destroy = async (req, res) => {
if (!await authorize(req, res, true)) {
return res.status(400).json({ success: false, errors: "unauthorized" })
}
await sequelize.query('SET FOREIGN_KEY_CHECKS=0;', { type: sequelize.QueryTypes.SELECT });
await Annoucement.destroy({
where: { id: req.params.id }
}
).then((result) => {
console.log(result);
res.status(200).json({ success: true })
}).catch((err) => {
console.log(err)
res.status(400).json({ success: false, errors: err.errors })
});
}

The QueryType you send tells Sequelize how to format the results. If you are performing SET and send QueryType.SELECT you will get an error because it tries to use .map() on an object:
const results = await sequelize.query("SET NAMES utf8mb4;", {
type: sequelize.QueryTypes.SELECT }
);
// -> TypeError: results.map is not a function
Sadly, in many places the docs confuse Raw Query (sending SQL in plain text) and using QueryTypes.RAW (which only should be used to format the results of queries that are not SELECT, UPDATE, etc.). Thus, one could assume that if you are making a Raw Query you should use the same QueryType to make the query "raw". At the very least, we should be able to assume it only affects how data is returned. The Sequelize documentation:
If you are running a type of query where you don't need the metadata,
for example a SELECT query, you can pass in a query type to make
sequelize format the results
Confusingly, if you are using a SELECT then none of these examples cause issues:
sequelize.query("SELECT * FROM table");
sequelize.query("SELECT * FROM table", { type: sequelize.QueryTypes.SELECT });
sequelize.query("SELECT * FROM table", { type: sequelize.QueryTypes.UPDATE });
sequelize.query("SELECT * FROM table", { type: sequelize.QueryTypes.RAW });
But if you use RAW on an UPDATE Sequelize tries to map an object 🙄
sequelize.query("UPDATE table SET createdAt = NOW();", {
type: sequelize.QueryTypes.RAW }
);
There was an uncaught error TypeError: results.map is not a function
at Query.handleSelectQuery ([...]/node_modules/sequelize/lib/dialects/abstract/query.js:261:24)
at Query.formatResults ([...]/node_modules/sequelize/lib/dialects/mysql/query.js:123:19)
at Query.run ([...]/node_modules/sequelize/lib/dialects/mysql/query.js:76:17)
at processTicksAndRejections (node:internal/process/task_queues:94:5)
at async [...]/node_modules/sequelize/lib/sequelize.js:619:16
So, because you are using SET you could, as #Anatoly says, change from QueryTypes.SELECT to QueryTypes.RAW to avoid the error. But if you don't need the results then don't pass a QueryType at all.
await sequelize.query('SET FOREIGN_KEY_CHECKS=0;');
// -> keep on keepin' on

Related

field in mongoose model is required : true but it is being created in postman

i am trying to give only name in the body and want error in the postman ...but for the status response in postman is 201 created but it is throwing error in console as
UnhandledPromiseRejectionWarning: ValidationError: User validation failed: password: Path password is required., email: Path email is required.
at model.Document.invalidate (C:\projects\MERN\backend\node_modules\mongoose\lib\document.js:2564:32)
at C:\projects\MERN\backend\node_modules\mongoose\lib\document.js:2386:17
at C:\projects\MERN\backend\node_modules\mongoose\lib\schematype.js:1181:9
at processTicksAndRejections (internal/process/task_queues.js:79:11)
(node:6524) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:6524) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
why there is no error in postman???????????
const mongoose = require('mongoose')
const userSchema = new mongoose.Schema({
name:{
type : String,
required : true
},
email:{
type : String,
required : true,
unique:true,
},
password:{
type : String,
required : true,
minlength: 7
},
date:{
type :Date,
default: Date.now
}
})
const User = mongoose.model('User',userSchema)
module.exports = User
router.post("/", async (req, res) => {
try {
const user = await new User(req.body);
user.save();
res.status(201).send({user});
} catch (e) {
res.status(500).send(e);
}
});
consider that your node application throws some error right and crashes as you describe well above. Because your node app is interfacing with the internet you need to devise a way to interpret the error from you app into to an error that is known by the internet also, that way postman will be able to tell that an error has occured...So how do we achieve this, the answer is error handling...
We will use your User model as you have described, and consider the code below it...
router.post("/", async (req, res) => {
try {
const user = await new User(req.body);
// One important thing to note is that the return of this function call below is
// a Promise object which means that it executes asynchrounously and from the error
// log you have above, it is the reason your app is crashing...
user.save();
res.status(201).send({user});
} catch (e) {
res.status(500).send(e);
}
});
So then lets fix it...
router.post("/", async (req, res) => {
const user = await new User(req.body);
return user.save()
// the then call simply accepts a callback that is executed after the async is complete
.then((result) => res.status(201).send({user}))
// this catch will be called in case the call encounters an error during execution
.catch((error) => res.status(500).send(error));
});
Note now we handle the error in the catch by responding to the HTTP request as you have with a 500 code...and also sending the error along with the response

NodeJS - How to deal with UnhandledPromiseRejectionWarning?

I am fairly new to Node JS and so I am struggling a bit.
I am trying to read files for google drive using their API, from my Node Js code.
I am having the following code
router.get('/', function (req, res, next) {
var pageToken = null;
// Using the NPM module 'async'
async.doWhilst(function (callback) {
drive.files.list({
q: "mimeType='image/jpeg'",
fields: 'nextPageToken, files(id, name)',
spaces: 'drive',
pageToken: pageToken
}, function (err, res) {
if (err) {
// Handle error
console.error(err);
callback(err)
} else {
res.files.forEach(function (file) {
console.log('Found file: ', file.name, file.id);
});
pageToken = res.nextPageToken;
callback();
}
});
}, function () {
return !!pageToken;
}, function (err) {
if (err) {
// Handle error
console.error(err);
} else {
// All pages fetched
}
})
res.render('index', { title: 'Express' });
});
The above code is giving me the following error when i send the get request
(node:13884) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'forEach' of undefined
at E:\nodejs\newcelebapi\routes\index.js:49:17
at E:\nodejs\newcelebapi\node_modules\googleapis-common\build\src\apirequest.js:43:53
at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:13884) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:13884) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
The issue is in the following line
res.files.forEach(function (file) {
I've tried everything I could and gave up understanding the problem.
Could you please help me with this?
Thanks!
Per this example in the doc, you want to be using:
res.data.files.forEach(...)
not:
res.files.forEach(...)
And, it looks like as soon as you get by that problem, you will have another problem because you are calling res.render() in the wrong place. And, when you fix that, you will have an issue with redefining res in your Google callback which will hide the higher level res that you need for res.render().
I would strongly recommend that you not use the async library here. It doesn't seem like it's needed here and it just complicates things. And, if you did need help doing coordination of asynchronous operations, promises is the modern way to do so.
You don't show what you're trying to do with the resulting files (other than logging them), but here's a simple implementation that does that:
router.get('/', function (req, res, next) {
var pageToken = null;
drive.files.list({
q: "mimeType='image/jpeg'",
fields: 'nextPageToken, files(id, name)',
spaces: 'drive',
pageToken: pageToken
}).then(response => {
let files = response.data.files;
files.forEach(file => console.log('Found file: ', file.name, file.id))
res.render('index', { title: 'Express' });
}).catch(err => {
console.log(err);
res.sendStatus(500);
});
});
Note, that I named the parameter from drive.files.list() to be named response instead of res so I can access both res from the router.get() callback and response from the drive.files.list() callback. You gave them both the same name res which means you can't access the router.get() parameter of the same name.

asynchronous issues adding to a map in mongoose

I am trying to add my googleID (object) to a map in another mongoose schema. I stringify my user id object, and during my test code I get thrown this error:
(node:293528) UnhandledPromiseRejectionWarning: ValidationError: collection validation failed: likes.5dbf6205bdcd5e5f78536447: Cast to ObjectId failed for value "110840542851551561690" at path "likes.$*"
at new ValidationError (C:\files\node_modules\mongoose\lib\error\validation.js:30:11)
at model.Document.invalidate (C:\files\node_modules\mongoose\lib\document.js:2333:32)
at Map.set (C:\files\node_modules\mongoose\lib\types\map.js:71:26)
at C:\files\app.js:123:30
at C:\files\node_modules\mongoose\lib\model.js:4589:16
at C:\files\node_modules\mongoose\lib\query.js:4323:12
at process.nextTick (C:\files\node_modules\mongoose\lib\query.js:2805:28)
at process._tickCallback (internal/process/next_tick.js:61:11)
(node:293528) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:293528) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
My Post request from client.js:
const likesForm = document.getElementById("test");
likesForm.addEventListener("submit", function (evt) {
evt.preventDefault();
console.log(event.target.id)
const [likeString, itemId] = evt.target.id.split("-");
vote(
likeString === "like"
? "1"
: "-1",
itemId
);
}, false);
async function vote (voteInc, itemId) {
const route = `/like/${itemId}`;
const response = await fetch(route, {
method: 'POST',
body: JSON.stringify({"like": voteInc}),
headers: {
'Content-Type': 'application/json'
}
});
const result = await response.json();
console.log(result);
}
Server-side post:
app.post("/like/:id",(req,res)=>{
const id = req.params.id;
const like = req.body.like;
console.log(like);
console.log(id);
if(req.isAuthenticated()){
linkscr.user.findById(req.user.id, (e,foundUser)=>{
if(e){
console.log(e);
}else{
//if like = 1
if(like==1){
linkscr.collection.findById(id, function(error,result){
if(error){
console.log(error);
}else{
result.likes.set(foundUser._id.toString(),foundUser.googleId);
result.save();
}
})
console.log("not voted yet. Add 1 and added to like");
}else{
linkscr.collection.findById(id, function(error,result){
if(error){
console.log(error);
}else{
result.dislikes.set(foundUser._id.toString(),foundUser.googleId);
result.save();
}
})
console.log("not voted yet. Add 1 and added to dislike");
};
};
});
}else{
res.redirect("/");
}
});
My likes/dislikes schema:
likes : {
type: Map,
of: {
type: mongoose.Schema.Types.ObjectId,
ref: "User" }
},
dislikes : {
type: Map,
of: {
type: mongoose.Schema.Types.ObjectId,
ref: "User" }
},
How the Schema is initially saved:
likes : {[User._id]:User},
dislikes : {},
Thanks for any and all help. You're my only hope Stack!
I first thought this was a mongoose issue with how i was treat my objects but it looks like this is more to do with the async stuff. Admittedly that's my biggest weakness in programming at the time writing this.
EDIT: From what I'm looking at from documentation mongoose can't set objects only strings. Mongo can not mongoose.
Edit 2: My bad I put in the wrong Id in the wrong place. foundUser._id.toString() ,foundUser
In order to create maps in mongoose, the key **Must be in the form of a string. Additionally Your schema (which wasn't initially shared) wanted the object_id not the google passportID. For the sake of helping out future generations I will provide an edit in the original post. Simplifying with foundUser will work in this case.
result.likes.set(foundUser._id.toString(), foundUser);

How to fix 'UnhandledPromiseRejectionWarning: ReferenceError:'?

I'm participating on this event called Semana OmniStack 9.0, on which we are currently developing the backend of an app on NodeJS with MVC and MongoDB, so in one of my controllers there is this error popping up 'UnhandledPromiseRejectionWarning: ReferenceError: Spot is not defined' which I tried to solve, but with no luck.
I already checked and compared my code with the Lecturer's, I think that I'm messing up with something on the async await side of JS, which I never have coded before.
This is my SpotController:
const spot = require('../models/Spot');
module.exports = {
async store(req, res) {
const { filename } = req.file;
const { company, techs, price } = req.body;
const { user_id } = req.headers;
const spot = await Spot.create({
user: user_id,
thumbnail: filename,
company,
techs: techs.split(',').map(tech => tech.trim()),
price
});
return res.json(spot);
}
};
And this is the Spot model for the DB (which is MongoDB):
const mongoose = require('mongoose');
const SpotSchema = new mongoose.Schema({
thumbnail: String,
company: String,
price: Number,
techs: [String],
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
});
module.exports = mongoose.model('Spot', SpotSchema);
And after I run Insomnia (it's a program similar to Postman), the app crashes and throw this error:
(node:13956) UnhandledPromiseRejectionWarning: ReferenceError: Spot is not defined
at store (C:\Users\sadkevin\Desktop\Programs\Rocketseat\SemanaOmnistack9\backend\src\controllers\SpotController.js:9:22)
at Layer.handle [as handle_request] (C:\Users\sadkevin\Desktop\Programs\Rocketseat\SemanaOmnistack9\backend\node_modules\express\lib\router\layer.js:95:5)
at next (C:\Users\sadkevin\Desktop\Programs\Rocketseat\SemanaOmnistack9\backend\node_modules\express\lib\router\route.js:137:13)
at Immediate.<anonymous> (C:\Users\sadkevin\Desktop\Programs\Rocketseat\SemanaOmnistack9\backend\node_modules\multer\lib\make-middleware.js:53:37)
at runCallback (timers.js:706:11)
at tryOnImmediate (timers.js:676:5)
at processImmediate (timers.js:658:5)
(node:13956) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was
not handled with .catch(). (rejection id: 1)
(node:13956) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
After I sent the data with Imsonia it should return me a JSON file, any ideas guys?

Calling a promise in a test get error 400 in NodeJS

I'm trying to use Contentful, a new JS library for building static websites. I want to use it in Node JS.
I created an app file like this (the name is getContent.js):
'use strict';
var contentful = require('contentful')
var client = contentful.createClient({
space: '****',
accessToken: '****'
});
module.exports = client;
function getEntry() {
return client.getEntry('******')
.then(function (entry) {
// logs the entry metadata
console.log(entry.sys)
// logs the field with ID title
console.log(entry.fields.channelName)
})
}
Then I created a test (getContent.test.js) like this:
'use strict';
let chai = require('chai');
let should = chai.should();
var expect = chai.expect;
var rewire = require("rewire");
let getContent = rewire("./getContent.js");
describe('Retreive existing', () => {
it('it should succeed', (done) => {
getContent.getEntry({contentName:'****'
}, undefined, (err, result) => {
try {
expect(err).to.not.exist;
expect(result).to.exist;
// res.body.sould be equal
done();
} catch (error) {
done(error);
}
});
});
});
but I obtain this error:
Retreive existing (node:42572) UnhandledPromiseRejectionWarning:
Error: Request failed with status code 400
at createError (/Users/ire/Projects/SZDEMUX_GDPR/api/node_modules/contentful/dist/contentful.node.js:886:15)
at settle (/Users/ire/Projects/SZDEMUX_GDPR/api/node_modules/contentful/dist/contentful.node.js:1049:12)
at IncomingMessage.handleStreamEnd (/Users/ire/Projects/SZDEMUX_GDPR/api/node_modules/contentful/dist/contentful.node.js:294:11)
at emitNone (events.js:111:20)
at IncomingMessage.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1064:12)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
at process._tickCallback (internal/process/next_tick.js:180:9) (node:42572) UnhandledPromiseRejectionWarning: Unhandled promise
rejection. This error originated either by throwing inside of an async
function without a catch block, or by rejecting a promise which was
not handled with .catch(). (rejection id: 3) (node:42572) [DEP0018]
DeprecationWarning: Unhandled promise rejections are deprecated. In
the future, promise rejections that are not handled will terminate the
Node.js process with a non-zero exit code.
Do you know what I'm missing? the promise is ok, I already tested it with a simple node getContent.js
I am seeing few issues with your code:
1. Invalid Args
In your test function, in getContent.js, you are passing an argument to the getEntry method (return client.getEntry('******'), whereas you are passing an object in the test (getContent.getEntry({}))
2. Mixing Promises & Callbacks
it('it should succeed', (done) => {
getContent.getEntry("****")
.then((result) => {
console.log(result);
try {
expect(result).to.exist;
// res.body.sould be equal
done();
} catch (error) {
done(error);
}
})
.catch(error => {
console.log(error);
done(error)
})
});
3. Source of Unhandled Promise rejection is not clear:
Is it coming from your test function in getContent.js, or, is it coming from your actual test?
Probably, this could also come from,
expect(err).to.not.exist;
expect(result).to.exist;
Always catch errors in Promises and reject it with proper reason to avoid issues like this.
Could you please update your code and repost it, so that its clear for other users?

Categories