I've recently started studying about TypeScript, and came across the Starter Project from the docs. Everything looks pretty straight forward, but there is one little part of the code that I just couldn't understand.
Here it is:
// Connect to MongoDB
const mongoUrl = MONGODB_URI;
(<any>mongoose).Promise = bluebird;
mongoose.connect(mongoUrl).then(
() => {},
).catch(err => {
console.log("MongoDB connection error. Please make sure MongoDB is running. " + err);
});
And the confusing part to me is this line:
(<any>mongoose).Promise = bluebird;
The <any>mongoose syntax remembers me of a type casting, but I don't think that is what is really happening here, since we have the bluebird module assigned to the .Promise part.
So if anyone is able to clear this out, I'd appreciate it pretty much.
<any>mongoose is indeed type casting, albeit the old syntax. The more current form would be (mongoose as any).Promise = bluebird. It means that you take the reference to mongoose and ignore its actual type, and treat it as any.
This prevents compile-time errors from type mismatches with mongoose.
In general, you should not cast to any, and you should look into why that is required of you in this case and see if you can avoid it.
Related
Suddenly, I started getting this error on my application when the node engine was upgraded to 10.7.0
TypeError [ERR_INVALID_CALLBACK]: Callback must be a function
Code which was working with node 4.5: fs.writeFile(target, content);
After a bit of debugging I found this in node_internal/fs.js:
function writeFile(path, data, options, callback) {
callback = maybeCallback(callback || options);
...
}
function maybeCallback(cb) {
if (typeof cb === 'function')
return cb;
throw new ERR_INVALID_CALLBACK();
}
Certainly, if do not pass a third/fourth argument here, my code will fail. I want to know is there any way to mitigate this problem. Or if not, what could be the motivation behind such a breaking change. After all, fs.writeFile() is such a basic operation, issues such as these are really a pain while upgrading.
Node.js has documented the purpose for this change: https://github.com/nodejs/node/blob/master/doc/api/deprecations.md#dep0013-fs-asynchronous-function-without-callback
There is a lot more discussion here: https://github.com/nodejs/node/pull/12562#issuecomment-300734746
In fact it seems like some developers agree with you, however the decision has been made and the callback is now required.
There is no mitigation per se; you will just have to add a callback. Even an empty one will work okay:
fs.writeFile(target, content, () => {});
I understand this may require a lot of changes for currently working code, but in fact it might be a good opportunity for you to add error handling as well.
I know this question has been asked a few times, but none seem to answer the particular part of using the query results for later.
I also know the problem resides on the fact that queries are asynchronous, and perhaps this is the reason I cannot seem to find a satisfactory answer.
Here's what I'm trying to do:
I have a node project with several sections, each section with different content. These sections have individual properties, which I decided to store in a Model for later use.
So far (and for simplicity sake) I have the following schema:
const SectionSchema = new Schema({
name: String,
description: String
})
const Section = mongoose.model('Sections',SectionSchema)
I'd like to retrieve this data to be used in one of my layouts (a navigation header), so I tried something like this:
const express = require('express')
const app = express()
Section.find().then(function(docs){
app.locals.sections = docs
})
console.log(app.locals.sections) // undefined
This obviously doesn't quite work due to find() being asynchronous, or rather, it does work but the values are populated at a different time. I know that if I do the console.log check inside the function I'd get a result, but that's not the concern, I want to store the data in app.locals so that I could later use it in one of my layouts.
Ideally I'd like to load this data once, before the server begins to listen to requests.
Feel free to correct me if I've made any wrong assumptions, I'm very new to node, so I don't quite know how to approach things quite yet.
Thanks in advance.
EDIT: I should've mentioned I'm using express.
Your node app will likely be comprised of route handlers for http requests. app.locals.section will be undefined if you call it outside of the callback, but it will exist in the route handler.
Let's say you were using something like express or restify:
const app = restify.createServer()
app.get('/', (req, res) => {
return res.json(app.locals.sections)
})
Section.find().then(function(docs){
app.locals.sections = docs
})
console.log(app.locals.section) // is undefined
app.listen(8080-, ()=>{
console.log('Server started 🌎 ',8080)
})
Actually, it might be undefined if the database call took a long time and or a user hit the app super soon after startup. Starting the server in the callback would ensure app.locals.section existed under every scenario:
Section.find().then(function(docs){
app.locals.sections = docs
app.listen(8080-, ()=>{
console.log('Server started 🌎 ',8080)
})
})
You can use async/await within a function to make it seem like you aren't using promises. But you can't use it at the top level of your module. See here: How can I use async/await at the top level?
It really would be fairly idiomatic to do all your app startup in a promise chain. It's a style of coding you are going to see a lot of.
Section.find().then((docs)=>{app.locals.sections = docs})
.then (()=>{/*dosomething with app.locals.sections */})
.then(startServer)
function startServer() {app.listen(8080-, ()=>{
console.log('Server started 🌎 ',8080)
})}
I'm trying to do a simple command line database transformation with node.js and sequelize. I've simplified my errant code down to the following, but it never returns:
// Set up database connection and models
var models = require('../models_sequelize');
models.User.findOne()
.then(a => {
console.log(a.name);
});
I get a name printed, but then the script hangs. What is wrong? How do I debug this to see what's stuck? I get the impression that there's an orphan promise that's not being fulfilled, but I don't understand where or why. I must be missing something obvious.
If I run the same interactively from the node console, it returns fine.
Sirko's comment re: close() gave me something to go on. I can stop the hanging with the following code:
var models = require('../models_sequelize');
models.User.findOne()
.then(a => {
console.log(a.name);
models.sequelize.close();
})
Alternatively, this seems to work too as I guess it's doing exactly the same thing:
var models = require('../models_sequelize');
models.User.findOne()
.then(a => {
console.log(a.name);
})
.finally(() => {
models.sequelize.close();
});
I also found something about connection pooling timeouts, but I don't think that affects my simple use case. I imagine it'll come into play in more complicated examples.
Would still like to find a good reference as to why this is necessary rather than just my guess.
im having problems understanding how to talk 'up and down' between app.js and modules...
I think its with a callback but i've also seen things like self._send(), this.send() and module.exports.emit
I'm quite confused.
I recently installed pdfkit from npm (quite good 6/10 :p) I want to learn by improving it slightly though by adding a done event/callback for doc.write().
I know its not that important but i've been looking through my installed modules and that is probably the easiest example of code that wouldn't hurt to have a 'DONE' I also figured this function would be good to learn from as it uses fs.writeFile which has a function(){} that fires when its finished writing so the fact that i can see where in the code it ends makes it an easy learning tool.
I've modified the code a few times tried to compare modules to see where similar things have been done but i just keep breaking it with errors, i don't feel like i'm getting anywhere:
inside the pdfkit module document.js i've made changes:
var EventEmitter = require('events').EventEmitter;//ben
module.exports = new EventEmitter();//ben
PDFDocument.prototype.write = function(filename, fn, callback) {//ben added callback
return this.output(function(out) {
return fs.writeFile(filename, out, 'binary', fn, function(){//ben added finished function
//module.exports.emit('pdf:saved');//ben
callback();//ben
});
});
};
in my app.js:
doc.write('public_html/img/'+_.c+'_'+_.propertyid+'.pdf',function(){console.log('pdf:saved');});
//doc.on('pdf:saved',function(){console.log('pdf:saved');});
I'm also not really sure what i'm querying on google, please can someone help me?
EventEmitter is required to create objects with event storage, and emit/catch events.
While what you are using in your example is called 'callback'.
It is two different ways, and can be sort of cross used. Sometimes it is good to use events, but sometimes just callback is enough.
The best way to have head around it: play with callbacks (forget about events for now). Try to think of different uses of callbacks and maybe even have callback function and pass it around. Then come to callback chains. And only after start playing with EventEmitter. Remember that EventEmitter is different thing from callbacks, with sometimes compatible use cases, but generally is used in different cases.
Here is your code, simplified with same functionality as you have/need atm:
PDFDocument.prototype.write = function(filename, callback) {
this.output(function(out) {
fs.writeFile(filename, out, 'binary', callback);
});
};
And use it the way you already do.
Do not try to generate garbage of code that will only complicate everything - it is better to study speficic areas seperatelly, and then switch to next one. Otherwise will mess up in mind.
FIXED
fn is the callback function!
PDFDocument.prototype.write = function(filename, fn) {
return this.output(function(out) {
return fs.writeFile(filename, out, 'binary', fn);
});
};
and by naming my callback function to fn it works!
doc.write('public_html/img/'+_.c+'_'+_.propertyid+'.pdf',function fn(){console.log('pdf:saved');});
for me that is a massive learning mountain climbed!!
I can't find any decent documentation on this that contains any depth when requiring with app.resource.
The only information that I can find is creating the variable within the current file. Here
The current code that I have is below:
var favs = app.resource('favs', require('./modules/favs'));
favs.map('get', '/user', favs.buses);
However it comes back saying that it is undefined?
In the module favs I have.
exports.buses = function (req, res) {
res.render('favs/buses', {
title: 'Bus Stops'
});
});
You have a syntax error in favs.js: The last right bracket ) is redundant.
Apart from that, you seem to conflate the actual module with the resource object you get back from app.resource. You want to pass a reference to the request handler you want to invoke when a visitor hits the path (in your case, /favs/user). So what you want is something like:
var favs = require('./modules/favs'),
favsResource = app.resource('favs', favs);
favsResource.map('get', '/user', favs.buses);
If you feel a little lost dealing with express-resource, I encourage you to begin with plain express, and only start using express-resource when you are more familiar with how express works. TJ's helper modules have a tendency to be lacking in documentation, and you should use them only if you feel comfortable reading the code, IMO.