How do I perform an `around` or `aroundEach` with mocha? - callback

Mocha provides before, beforeEach, after, and afterEach. I'm looking for something like around or aroundEach, but I can't find anything in the mocha docs about it.
My use case is that I'd like to wrap each test in a DB transaction, performing a rollback after each one is run. I envision doing something like this:
aroundEach(function (testRunner, done) {
sequelize.transaction().next(function (t) {
testRunner();
t.rollback().done(done);
});
});
As an alternative/workaround, something like this exists as an option (although it feels less clean):
beforeEach(function (done) {
sequelize.transaction().next((t) => {
this.transaction = t;
done();
});
});
afterEach(function (done) {
this.transaction.rollback().done(done);
});

Related

How mongoose middleware works and what is next()?

userSchema.pre('save',async function(next){
//hash the password before saving user to database
next()
})
Hey guys I'm trying to understand the concept of middleware in mongoose. Assuming that I have an userSchema that I run the pre hook on to hash the password before saving the user to the database. On the surface, as far as I understand, the above code that I have will hash the password (not the important part for this question) and then call next() to signal that the function is done. However, I am trying to understand how things work under the hood. I want to know what is next() ? Can you guys walk me through an example of how everything works together under the hood from start to end once the code get executed or somehow help me to have a better understanding of this concept? Thanks
Short : with the pre method you can register listeners for certain events of your Schemas. So pre('save', callback) will fire whenever you save a document of said Model. pre means it will execute before the event, so it can be used (for example) to hash a password before saving it to the document.
However, you have several options to define them, see below :
The combination of using an async callback function and providing the next parameter is not necessary, you can either :
use normal callback with next parameter
the next parameter is a function provided to you by mongoose to have a way out, or to tell mongoose you are done and to continue with the next step in the execution chain. Also it is possible to pass an Error to next it will stop the execution chain.
schema.pre('save', function(next) {
// do stuff
if (error) { return next(new Error("something went wrong"); }
return next(null);
});
use async callback
Here the execution chain will continue once your async callback has finished. If there is an error and you want to break/stop execution chain you just throw it
schema.pre('save', async function() {
// do stuff
await doStuff()
await doMoreStuff()
if (error) { throw new Error("something went wrong"); }
return;
});
Straight from the docs : https://mongoosejs.com/docs/middleware.html#pre
Example
const { Schema, model } = require('mongoose');
const SomeSchema = new Schema ({
name : { type : String }
});
SomeSchema.pre('save', function (next) {
console.log('pre save fired!');
return next();
});
const Some = model('Some', SomeSchema);
console.log('before create');
const doc = new Some({ name : 'test' });
doc.save((err) => {
console.log('after saved');
});
This will output
before create
pre save fired!
after saved

Sails.js 1.0 helpers chaining as Promises

I'm new to Sails.js and I'm looking to develop a new application using sail.js and in this application, I want to respond to a POST request as quickly as possible, then handle a number of tasks with the payload asynchronously. Ideally I'd have a helper for each step of the tasks I want to carry out on the payload and chain them all asynchronously in the action. I've been trawling through the docs and can't seem to find a way to do this.
Is this the right way to approach this issue (if so how/can you point me to docs) or are there alternative ways to handle this issue that I have overlooked?
Thanks
With ES6, you can use helpers both with async/await or as promises.
const temp1 = await sails.helpers.stepone();
const temp2 = await sails.helpers.steptwo( temp1 );
let result = await sails.helpers.stepthree( temp2 );
// use result here
OR
sails.helpers.stepone
.then(sails.helpers.steptwo)
.then(sails.helpers.stepthree)
.then(result => {
// use result here
});
Just set up your service methods as promises and resolve early. You can import bluebird, for example, to accomplish this.
In your controller:
myPostEndpoint: (req, res) => {
return MyProcessorService.initProcessing(req.body).then(res.json);
}
And in your service MyProcessorService:
var Promise = import('bluebird');
//... other init code
module.exports = {
initProcessing: data => {
//do some validation...
// then just resolve and continue
Promise.resolve({ status: 'processing'});
return MyProcessorService.step1(data)
.then(MyProcessorService.step2)
.then(MyProcessorService.step3)//and so on....
},
step1: dataFromInit => {
//do stuff and resolve for step2
},
step2: dataFromStep1 => {
//do stuff and resolve for step3
},
step3: dataFromStep2 => {
//do stuff and resolve
},
//and so on
}
You could also set up a worker queue with something like Bull and Redis to send off jobs to and run in a WorkerService or separate worker app.

mongodb force synchronous to find documents [duplicate]

I'm using the Node.JS driver for MongoDB, and I'd like to perform a synchronous query, like such:
function getAThing()
{
var db = new mongo.Db("mydatabase", server, {});
db.open(function(err, db)
{
db.authenticate("myuser", "mypassword", function(err, success)
{
if (success)
{
db.collection("Things", function(err, collection)
{
collection.findOne({ name : "bob"}, function(err, thing)
{
return thing;
});
});
}
});
});
}
The problem is, db.open is an asychronous call (it doesn't block), so the getAThing returns "undefined" and I want it to return the results of the query. I'm sure I could some sort of blocking mechanism, but I'd like to know the right way to do something like this.
ES 6 (Node 8+)
You can utilize async/await
await operator pauses the execution of asynchronous function until the Promise is resolved and returns the value.
This way your code will work in synchronous way:
const query = MySchema.findOne({ name: /tester/gi });
const userData = await query.exec();
console.log(userData)
Older Solution - June 2013 ;)
Now the Mongo Sync is available, this is the right way to make a synchronous MongoDB query in Node.js.
I am using this for the same. You can just write sync method like below:
var Server = require("mongo-sync").Server;
var server = new Server('127.0.0.1');
var result = server.db("testdb").getCollection("testCollection").find().toArray();
console.log(result);
Note: Its dependent on the node-fiber and some issues are there with it on windows 8.
Happy coding :)
There's no way to make this synchronous w/o some sort of terrible hack. The right way is to have getAThing accept a callback function as a parameter and then call that function once thing is available.
function getAThing(callback)
{
var db = new mongo.Db("mydatabase", server, {});
db.open(function(err, db)
{
db.authenticate("myuser", "mypassword", function(err, success)
{
if (success)
{
db.collection("Things", function(err, collection)
{
collection.findOne({ name : "bob"}, function(err, thing)
{
db.close();
callback(err, thing);
});
});
}
});
});
}
Node 7.6+ Update
async/await now provides a way of coding in a synchronous style when using asynchronous APIs that return promises (like the native MongoDB driver does).
Using this approach, the above method can be written as:
async function getAThing() {
let db = await mongodb.MongoClient.connect('mongodb://server/mydatabase');
if (await db.authenticate("myuser", "mypassword")) {
let thing = await db.collection("Things").findOne({ name: "bob" });
await db.close();
return thing;
}
}
Which you can then call from another async function as let thing = await getAThing();.
However, it's worth noting that MongoClient provides a connection pool, so you shouldn't be opening and closing it within this method. Instead, call MongoClient.connect during your app startup and then simplify your method to:
async function getAThing() {
return db.collection("Things").findOne({ name: "bob" });
}
Note that we don't call await within the method, instead directly returning the promise that's returned by findOne.
While it's not strictly synchronous, a pattern I've repeatedly adopted and found very useful is to use co and promisify yield on asynchronous functions. For mongo, you could rewrite the above:
var query = co( function* () {
var db = new mongo.Db("mydatabase", server, {});
db = promisify.object( db );
db = yield db.open();
yield db.authenticate("myuser", "mypassword");
var collection = yield db.collection("Things");
return yield collection.findOne( { name : "bob"} );
});
query.then( result => {
} ).catch( err => {
} );
This means:
You can write "synchronous"-like code with any asynchronous library
Errors are thrown from the callbacks, meaning you don't need the success check
You can pass the result as a promise to any other piece of code

Meteor code must always run within a fiber when deploy in meteor server

I kept having this error when i deploy my app onto meteor cloud server.
Meteor code must always run within a Fiber
at _.extend.get (app/packages/meteor/dynamics_nodejs.js:14:13)
at _.extend.apply (app/packages/livedata/livedata_server.js:1268:57)
at _.extend.call (app/packages/livedata/livedata_server.js:1229:17)
at Meteor.startup.Meteor.methods.streamTwit (app/server/server.js:50:24)
however, I have already wrapped within Fibers
streamTwit: function (twit){
var userid = '1527228696';
twit.stream(
'statuses/filter',
{ follow: userid},
function(stream) {
stream.on('data', function(tweet) {
Fiber(function(){
if(tweet.user.id_str === userid)
{
Meteor.call('addQn', tweet);
}
}).run();
console.log(tweet);
console.log('---------------------------------------------------------');
console.log(tweet.user.screen_name);
console.log(tweet.user.name);
console.log(tweet.text);
});
}
);
}
I don't know what's the reason but someone suggested that i should wrap it with Meteor.bindEnvironment instead. Hence, I did this:
streamTwit: function (twit){
this.unblock(); // this doesn't seem to work
console.log('... ... trackTweets');
var _this = this;
var userid = '1527228696';
twit.stream(
'statuses/filter',
{ follow: userid},
function(stream) {
stream.on('data', function(tweet) {
Meteor.bindEnvironment(function () {
if(tweet.user.id_str === userid)
{
Meteor.call('addQn', tweet);
}
}, function(e) {
Meteor._debug("Exception from connection close callback:", e);
});
console.log(tweet);
console.log('---------------------------------------------------------');
console.log(tweet.user.screen_name);
console.log(tweet.user.name);
console.log(tweet.text);
});
}
);
}
//add question method
addQn:function(tweet){
questionDB.insert({'tweet': tweet, 'date': new Date()});
}
but now it doesn't even work. I realise that this only happened when I tried to insert some data into mongodb.
May I know what is the problem with my code? Thanks!
All these codes were written in app/server/server.js
You shouldn't need to use Meteor.call on the server side. That is for client-side code only. Just call addQn directly or better yet, inline it since it's just one line of code.

JS node asynchronous handling of events

Can some one point me to or explain some kind of event based design pattern that handles the situation of waiting on two events to complete to perform an action.
I have a template that is loaded async and a database call that is also happening at the same time. I have a response that needs to be executed only when both of these tasks has completed.The only solution I can come up with is doing something ugly like putting in booleans that set to true on the event finish and then check to see if they are all true. Is there a better way to do this?
Just to add an example of either from Chris' answer:
Using async, https://github.com/caolan/async
async.parallel([
function(callback){
// query a database, lets say mongodb/mongoose
User.findOne({email: email}, function(err, user){
callback(err, user);
});
},
function(callback){
// Load a template from disk
fs.readFile('views/user.html', function (err, data) {
callback(err, data)
});
}
], function(err, results){
// Should have [user, template data]
});
Or with counters:
var user = false,
template = false,
count = 2;
function build_user_view(){
// user, template should be available
}
User.findOne({email: email}, function(err, userDoc){
user = userDoc;
--count || build_user_view();
});
fs.readFile('views/user.html', function (err, data) {
template = data;
--count || build_user_view();
});
There's no simple way to do this really, but there are lots of flow control libraries that handle this sort of thing. The simplest way might be to keep a global counter that increments when you start an async call, then decrements in the callback when it finishes. Each operation could check the counter when it finishes, and if it's zero trigger the response that depends on both being completed.