Durandal - Failed to load routed module Details: undefined is not a function - requirejs

What does the error "Failed to load routed module (edit/user/index). Details: undefined is not a function" mean?
I get this error intermittetly and my stack trace looks like this:
logError system.js?bust=1398976887311:92
(anonymous function) router.js?bust=1398976887311:362
l jquery.min.js:6
c.fireWith jquery.min.js:6
(anonymous function) jquery.min.js:6
l jquery.min.js:6
c.fireWith jquery.min.js:6
i.(anonymous function) jquery.min.js:6
(anonymous function) system.js?bust=1398976887311:260
(anonymous function) require.js:129
(anonymous function) require.js:1154
each require.js:57
Module.emit require.js:1153
(anonymous function) require.js:529
each require.js:57
onError require.js:522
Module.check require.js:893
(anonymous function) require.js:1111
(anonymous function) require.js:129
(anonymous function) require.js:1154
each require.js:57
Module.emit require.js:1153
Module.check require.js:924
Module.enable require.js:1141
Module.init require.js:778
callGetModule require.js:1168
context.completeLoad require.js:1530
context.onScriptLoad
I have a module global that looks like this:
define(['jquery', 'knockout', 'plugins/ajax'], function ($, ko,ajax) {
'use strict';
var obj = {};
obj.loading = ko.observable(false);
obj.activate = function () {
obj.loading.subscribe(function (newValue) {
if (newValue) {
$.blockUI({
css: {
border: 'none',
padding: '15px',
backgroundColor: '#333',
'-webkit-border-radius': '10px',
'-moz-border-radius': '10px',
opacity: 0.9,
color: '#fff',
fontSize: '26px',
fontFamily: "'Helvetica Neue', Helvetica"
},
overlayCSS: {
opacity: 0.2,
},
message: '<span>Please wait...</span>',
fadeIn: 0
});
}
else
$.unblockUI();
});
obj.promise = $.when(
ajax.wrap('Durandal/GetUnitModel', { Id: '1' }, function (response) {
ajax.updateModel(obj, 'unitModel', response.Model);
}),
ajax.wrap('Durandal/GetUserModel', { Id: '1' }, function (response) {
ajax.updateModel(obj, 'userModel', response.Model);
}),
ajax.wrap('Durandal/GetOfficeModels', { Id: '1' }, function (response) {
ajax.updateModel(obj, 'Offices', response.Model);
}),
ajax.wrap('Durandal/GetUserGroupModels', { Id: '1' }, function (response) {
ajax.updateModel(obj, 'UserGroups', response.Model);
})
);
return obj.promise;
};
return obj;
});
My edit user module that intermittently doesn't load (half the time it works fine) is:
define(['durandal/global','plugins/router', 'plugins/http', 'durandal/app', 'knockout', 'plugins/ajax', 'plugins/dialog', 'plugins/permissions', 'plugins/utility'], function (global,router, http, app, ko, ajax, dialog, permissions,utility) {
var vm = {};
vm.permissions = permissions;
vm.utility = utility;
vm.global = global;
vm.AddOffices = ko.computed(function () {
var ao = [];
$.each(global.Offices(), function (i, v) {
if (v.Name() != 'N/A' && v.Name() != 'Office of Afghanistan and Pakistan Affairs')
ao.push(v);
});
return ao;
});
vm.getUser = function (personId) {
if (personId == '0') {
return $.when(global.promise).then(function () {
ajax.updateModel(vm, 'newPersonRecord', {
"Email": ko.observable(""),
"FirstName": ko.observable(""),
"LastName": ko.observable(""),
"UserGroup": { Id: ko.observable("3"), Name: ko.observable("Viewer") },
"UserGroupId": ko.observable("3"),
"Office": { Id: ko.observable(global.Offices()[0].Id()), Name: ko.observable(global.Offices()[0].Name()) },
"OfficeId": ko.observable(global.Offices()[0].Id()),
"CotrExpirationDate": ko.observable(""),
"UserExpirationDate": ko.observable(Date.today().add(6).months().add(-1).days().toString('M/d/yyyy')),
"Id": ko.observable("0"),
"UnitId": global.userModel.UnitId(),
"UnitName": global.userModel.UnitName(),
"PasswordResetDate": ko.observable(""),
"Name": ko.observable(""),
"UserGroupName": ko.observable(""),
"OfficeName": ko.observable("")
});
});
}
else
return ajax.wrap('UserAdmin/GetUser', { PersonId: personId }, function (response) {
ajax.updateModel(vm, 'newPersonRecord', response.Model);
});
};
vm.activate = function (personId) {
return vm.getUser(personId);
};
vm.save = function () {
if ($("[name='validationError']:visible").length > 0) {
alert('Please correct all errors before continuing.');
return;
}
else {
if (vm.newPersonRecord.OfficeId() != '40')
ajax.wrap("UserAdmin/Update", vm.newPersonRecord, function (response) { if (!response.Success) alert(response.Message); else alert('User record saved.'); vm.back();});
else
ajax.wrap("UserAdmin/UpdatePartner", vm.newPersonRecord, function (response) { if (!response.Success) alert(response.Message); else alert('User recrord saved.'); vm.back(); });
}
};
vm.back = function () {
router.navigateBack();
};
vm.chars = function (str, numChars) {
if (str.length > numChars)
return false;
return true;
};
vm.validEmail = function () {
if (vm.newPersonRecord.Name().indexOf("#") == -1)
return false;
if (vm.newPersonRecord.Name().indexOf("’") != -1)
return false;
if (vm.newPersonRecord.Name().indexOf(",") != -1)
return false;
if (vm.newPersonRecord.Name().length < 4)
return false;
return true;
};
vm.emailExists = function () {
var emailExists = false;
$.each(viewModel.People(), function (index, value) {
if (value.Name() == newPersonRecord.Name())
emailExists = true;
});
return emailExists;
};
vm.cacheViews = false;
return vm;
});
My shells.js module looks like this:
define(['plugins/router', 'durandal/app', 'plugins/ajax', 'durandal/global', 'durandal/activator'], function (router, app, ajax, global, activator) {
var vm = {};
vm.global = activator.create();
//call this to refresh menu items
vm.rebuildRouter = function () {
return ajax.wrap('Durandal/GetMenuItems', { menuName:'viewmodels/shell.js' }, function (response) {
vm.router.deactivate();
vm.router.reset();
vm.router.routes = [];
vm.router.map(response.Model).buildNavigationModel();
vm.router.activate();
});
/* { route: 'Map*details', title: 'Map', moduleId: 'map/index', nav: true, hash: '#Map' },*/
};
vm.activate = function () {
var promise = vm.global.activateItem(global);
return $.when(promise, vm.rebuildRouter());
}
vm.refreshUnit = function () {
ajax.wrap('PostLogin/DurandalSwitchUnit', { unitId: vm.global().userModel.UnitId() }, function (response) { $.when(global.activate(),vm.activate()).then(function () { router.navigate();}); });
};
vm.router = router;
return vm;
});
Any help debugging this would be greatly appreciated. Has anyone else run into such an error, what did it mean? It would help to even know roughly where to look, why does Durandal throw this error, it says something is 'undefined' but what is it looking for that is undefined in this case?

Assuming you're using Durandal 2.x, change the following line in your module global:
define(['jquery', 'knockout', 'plugins/ajax'], function ($, ko,ajax) {...
to this:
define(['knockout', 'plugins/ajax'], function (ko,ajax) {...
See if that that solves the problem.

This error message led me down hours of wild goose chases.
Eventually I found and fixed an error in my code where I had attempted to use the underscore library and this is what was failing.
If you get this error message, anything could be wrong anywhere in your module. You probably put a symbol like _ or $ somewhere in your code and it isn't defined.

Related

Why on my NodeJS+Express REST API a promise calling my function fails while the same promise with setTimeout works?

I have a NodeJS+Express REST API method executing reverse geocoding (using Google's Maps API).
I'm trying to solve it with Promises but the 'then' is getting executed before my function returns with the answers from Google.
When testing the same code just calling a setTimeout, it works as expected. Please see comments in the code (simplify version).
app.get('/api/v1/events', verifyToken, async (req, res) => {
await db.poolPromise.then(pool => {
return pool.request()
.input('UserId', db.sql.UniqueIdentifier, res.authData.userId)
.input('DateFrom', db.sql.DateTime2(7), req.query.dateFrom)
.input('DateTill', db.sql.DateTime2(7), req.query.dateTo)
.output('UserIdAuthorized', db.sql.Bit)
.execute('sp')
}).then(result => {
let output = (result.output || {})
if (!output.UserIdAuthorized) {
res.sendStatus(403)
}
else if (result.recordset.length > 0) {
(new Promise( (resolve) => {
//resolve(123) // this one works as expected
//setTimeout(resolve, 3000, 'temp success') // this one works as expected
// *** this one get passed and the following then is being executed before it answers ***
resolve( getAddress_TEST(result.recordset) )
// **************************************************************************************
})).then(function (value) {
res.json(
{
meta: { count: 10 }, //this is just a sample
result: value // *** this one fails with undefined ***
})
})
} else {
res.sendStatus(404)
}
}).catch(err => {
res.sendStatus(500)
console.error(err)
})
});
const nodeGeocoder_options = {
provider: 'google',
apiKey: process.env.GOOGLE_API_KEY
}
async function getAddress_TEST(recordset) {
//sample recordset for debugging - as you dont have my database
recordset = [{'eventId':14205556,'Lat':54.57767,'Lon':-2.4920483},{'eventId':14205558,'Lat':54.57767,'Lon':-2.492048},{'eventId':14205579,'Lat':53.416908,'Lon':-2.952071},{'eventId':14205588,'Lat':52.644448,'Lon':-1.153185},{'eventId':14205601,'Lat':52.29174,'Lon':-1.532283},{'eventId':14205645,'Lat':52.644448,'Lon':-1.153185},{'eventId':14205801,'Lat':53.68687,'Lon':-1.498708},{'eventId':14206041,'Lat':51.471521,'Lon':-0.2038033},{'eventId':14206049,'Lat':51.471521,'Lon':-0.2038033},{'eventId':14206072,'Lat':51.471521,'Lon':-0.2038033}]
let geocoder = nodeGeocoder(nodeGeocoder_options)
let ps = []
for (var i = 0, length = recordset.length; i < length; i++) {
if (i == 0 || !(i > 0
&& recordset[i - 1].Lat == recordset[i].Lat
&& recordset[i - 1].Lon == recordset[i].Lon)) {
ps.push(new Promise(function (resolve) {
resolve(reverseGeocode(geocoder, recordset[i].Lat, recordset[i].Lon))
}))
} else {
ps.push('-')
}
}
await Promise.all(ps)
.then(function (values) {
for (var i = 0, length = values.length; i < length; i++) {
if (values[i] != '-') {
recordset[i].locationAddress = values[i]
} else {
recordset[i].locationAddress = recordset[i - 1].locationAddress
}
}
}).then(function () {
recordset.forEach(function (v) {
delete v.Lat
delete v.Lon
});
console.log(recordset)
return recordset
})
};
async function reverseGeocode(geocoder, lat, lon) {
let address = '+'
if (lat != 0 && lon != 0) {
await geocoder.reverse({ lat: lat, lon: lon })
.then(res => {
address = res[0].formattedAddress
})
.catch(err => {
console.error(err)
});
}
return address
};
I'm sure it is something simple that I'm missing here...
The basic problem is that your getAddress_TEST function returns a promise that fulfills with nothing (undefined), because it does not contain a return statement. The return recordset is in a then() callback, from where it affects the promise resolution of the awaited promise, but that result is thrown away.
If you want to use async/await, you should get rid of any new Promise and then calls:
app.get('/api/v1/events', verifyToken, async (req, res) => {
try {
const pool = await db.poolPromise
const result = await pool.request()
.input('UserId', db.sql.UniqueIdentifier, res.authData.userId)
.input('DateFrom', db.sql.DateTime2(7), req.query.dateFrom)
.input('DateTill', db.sql.DateTime2(7), req.query.dateTo)
.output('UserIdAuthorized', db.sql.Bit)
.execute('sp')
let output = (result.output || {})
if (!output.UserIdAuthorized) {
res.sendStatus(403)
} else if (result.recordset.length > 0) {
const value = await getAddress_TEST(result.recordset)
res.json({
meta: { count: 10 }, //this is just a sample
result: value
})
} else {
res.sendStatus(404)
}
} catch(err) {
res.sendStatus(500)
console.error(err)
}
});
const nodeGeocoder_options = {
provider: 'google',
apiKey: process.env.GOOGLE_API_KEY
}
async function getAddress_TEST(recordset) {
const geocoder = nodeGeocoder(nodeGeocoder_options)
const ps = recordset.map((record, i) => {
if (i == 0 || !(i > 0
&& recordset[i - 1].Lat == record.Lat
&& recordset[i - 1].Lon == recordLon)) {
return reverseGeocode(geocoder, recordset[i].Lat, recordset[i].Lon))
} else {
return '-'
}
});
const values = await Promise.all(ps)
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
for (var i = 0, length = values.length; i < length; i++) {
if (values[i] != '-') {
recordset[i].locationAddress = values[i]
} else {
recordset[i].locationAddress = recordset[i - 1].locationAddress
}
}
recordset.forEach(function (v) {
delete v.Lat
delete v.Lon
});
console.log(recordset)
return recordset
// ^^^^^^^^^^^^^^^^
}
async function reverseGeocode(geocoder, lat, lon) {
if (lat != 0 && lon != 0) {
const res = await geocoder.reverse({ lat: lat, lon: lon })
return res[0].formattedAddress
}
return '+'
}

Need help for mongoose .find()

I need the result of Mongoose's find().exec in the below format. Is it possible to format the result like that?
var myFunction = function(foo, bar) {
model1.find({ elem: foo, elem2: bar }).exec(function(err, data) {
if (err) {
/* ... */
}
if (data) {
if (data.passed == true) {
return { passed: true, point: data.point };
} else {
return { passed: false, point: data.point };
}
} else {
return { passed: false, point: "not tried" };
}
});
};
object = {
...
someitem: array.map(function(arr) {
return {
_id: program._id,
title: program.title,
slug: program.slug,
status: myFunction(arr._id, arr._id2) /* Like This */
};
});
...
}
and excuse me for My bad english :D
You have to return promise from the function in order to get the values which are coming form mongoose query.So change your function to be:
var myFunction = function(foo,bar) {
return new Promise(function(resolve, reject){
model1.find({elem : foo, elem2 : bar}).exec(function (err, data){
if(err){
/* Blablabla*/
reject(err);
}
if(data){
if(data.passed == true){
resolve({passed:true, point:data.point});
} else {
resolve({passed:false, point:data.point});
}
} else {
resolve({passed:false, point:'not tried});
}
});
});
}
Than if you want to call the function and get the value you have to do like:
let promises, obj_elem = [];
for(let i =0;i < array.length;i++){
promises.push(myFunction(array[i]._id, array[i]. _id2));
}
/* You can't do it sync manner so you have to use some kind of async process */
Promise.all(promises).then((result)=>{
for(let i =0;i < result.length;i++){
obj_elem.push({
_id: program._id,
title: program.title,
slug: program.slug,
status: result[i].passed
});
}
console.log(obj_elem); //here you will have values you want
});

Stubbing push notifications with sinon

I would like to test a function that sends a push notification. I would like to stub the notification send. I use mocha and sinon. I tried to stub with several syntax, but it's not working. One stub I tried:
var sender = sinon.createStubInstance(gcm.Sender);
var gcmReturn = {
multicast_id: 1,
success: 1,
failure: 1,
canonical_ids: 1,
results: [{
registration_id: 'xxxx',
message_id: 'yyy'
}, {
error: 'InvalidRegistration'
}]
}
sender.send = function() {
return gcmReturn;
}
The code to test:
var gcm = require('node-gcm');
// Function to test
NotificationService.prototype.sendSpecificNotification = function (data) {
var self = this;
// Process data to create the users, title and text parameters
return self.send(users, title, text)
.then(function(pushResults) {
// expect ...
})
};
NotificationService.prototype.send = function (users, title, text) {
var registrationIds = [];
users.forEach(function (user) {
var push = user.preferences != null ? user.preferences.push : false;
if (push) {
var regId = user.preferences.pushRegId;
registrationIds.push(regId);
}
});
var deferred = Q.defer();
if (registrationIds.length > 0) {
var message = new gcm.Message();
message.addData('message', text);
message.addData('title', title);
message.delayWhileIdle = false;
message.timeToLive = 24 * 60 * 60;
var currentDate = new Date();
var notId = currentDate.getHours() * 60 * 60 + currentDate.getMinutes() * 60 + currentDate.getSeconds();
message.addData('notId', notId);
var sender = new gcm.Sender(config.gcm.senderId);
// I want to stub that call
sender.send(message, registrationIds, function (err, result) {
if (err) {
deferred.reject(new Error(error));
} else {
deferred.resolve(result);
}
});
} else {
deferred.resolve('');
}
return deferred.promise;
}
EDIT: The test
it('Subscription Push', function () {
var sender = sinon.createStubInstance(gcm.Sender);
var gcmReturn = {
multicast_id: 1,
success: 1,
failure: 1,
canonical_ids: 1,
results: [{
registration_id: 'xxxx',
message_id: 'yyy'
}, {
error: 'InvalidRegistration'
}]
}
sender.send.returns(Q.resolve(gcmReturn));
return fixtureService.clearDatabase()
.then(function () {
return fixtureService.load('./test/subscription-push.json');
})
.then(function () {
return notificationService.sendSpecificNotification();
});
});
Have you tried using the sinon stub method? Example:
it('Subscription Push', function () {
var sender = sinon.createStubInstance(gcm.Sender);
var gcmReturn = {
multicast_id: 1,
success: 1,
failure: 1,
canonical_ids: 1,
results: [{
registration_id: 'xxxx',
message_id: 'yyy'
}, {
error: 'InvalidRegistration'
}]
}
sender.send.returns(Q.resolve(gcmReturn));
return fixtureService.clearDatabase()
.then(function () {
return fixtureService.load('./test/subscription-push.json');
})
.then(function () {
return notificationService.sendSpecificNotification();
});
});
UPDATE
You aren't using the stubbed methods at all, there is no magic going on behind the scenes here that stub the method automatically on the notificationService. You need to use the sender you created or just stub the method out directly on the notificationService.
it('Subscription Push', function () {
var sender = sinon.createStubInstance(gcm.Sender);
var gcmReturn = {
multicast_id: 1,
success: 1,
failure: 1,
canonical_ids: 1,
results: [{
registration_id: 'xxxx',
message_id: 'yyy'
}, {
error: 'InvalidRegistration'
}]
}
sender.send.returns(Q.resolve(gcmReturn));
return fixtureService.clearDatabase()
.then(function () {
return fixtureService.load('./test/subscription-push.json');
})
.then(function () {
// Here you should be using sender.sendSpecificNotification();
// Alternatively, you could simply stub out the method
// on the notificationService directoy and avoid using the sender at all.
// To stub out the method on the notificationService do this:
// sinon.stub(notificationService, 'send', function() { return Q.resolve(gcmReturn); });
return notificationService.sendSpecificNotification();
});
});

How to pass Parameter to spooky in nodejs

I'm trying to send the parametter countryCode to spookyjs function.
My question is how to do this , because when I wanna use the
countryCode inside spooky.then(function) the countryCode is empty
thank you a lot
This is the call code
var greetings = require("./get_country.js");
var countryCode = "ES";
greetings.getOne("ES");
This is the function code:
var Spooky = require('spooky');
module.exports = {
getOne: function(countryCode) {
var init = function(error) {
if (error) {
e = new Error('Failed to initialize SpookyJS');
e.details = error;
throw e;
}
spooky.start('http://www.domain.com/');
spooky.then(function() {
this.emit('return', this.evaluate(function() {
var raw_countries = document.querySelectorAll('#country-selector li.' + countryCode);
return raw_countries;
}));
});
spooky.run();
},
spooky = new Spooky({
child: {
transport: 'http'
},
casper: {
logLevel: 'debug',
verbose: true
}
}, init);
spooky.on('error', function(error, stack) {
console.error(error);
if (stack) {
console.log(stack);
}
});
spooky.on('return', function(data) {
console.log(data);
});
}};
You need to pass the required global variable to both spooky's then() as well as evaluate() functions to be able to access it as below
spooky.start('example.com/');
spooky.then([{ countryCode: countryCode }, function () {
this.emit('return', this.evaluate(function (countryCode) {
var raw_countries = document.querySelectorAll('#country-selector li.' + countryCode);
return raw_countries;
}), countryCode);
}]);
spooky.run();
Reference example

Issues with saving referenced objects with mongoose

This is my song schema. ignoring import statements
var SongSchema = new mongoose.Schema({
name: String,
genre: String,
artist: String,
album: String,
year: Number,
composer: String,
lyrics: String,
duration: Number // [seconds]
});
var Song = module.exports = mongoose.model('Song', SongSchema);
This is my playlist schema
var PlaylistSchema = new mongoose.Schema({
name: String,
genre: String,
songs: [{
details: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Song'
},
upvote_count: Number,
state: String,
type: String
}]
});
var Playlist = mongoose.model("Playlist", PlaylistSchema);
faulty code:
console.log("object:", song.details);
var newSong = new Song(song.details);
newSong.save();
console.log("song:", newSong);
newPlaylist.songs.push({
details: newSong._id,
upvote_count: song.upvote_count || 0,
state: song.state || SongState.QUEUED,
type: song.type || SongType.NOT_FROZEN
});
on saving this playlist using the above code I get the following error,
object: { name: 'String',
genre: 'String',
artist: 'String',
album: 'String',
year: 2010,
composer: 'String',
lyrics: 'String' }
song: strictMode=true, selected=undefined, shardval=undefined, saveError=undefined, validationError=undefined, adhocPaths=undefined, removing=undefined, inserting=undefined, version=undefined, , _id=undefined, populate=undefined, populated=undefined, wasPopulated=false, scope=undefined, _id=default, duration=modify, lyrics=modify, composer=modify, year=modify, album=modify, artist=modify, genre=modify, name=modify, , _id=true, , duration=true, lyrics=true, composer=true, year=true, album=true, artist=true, genre=true, name=true, , stateNames=[require, modify, init, default, ignore], ownerDocument=undefined, fullPath=undefined, domain=null, , _maxListeners=0, isNew=true, errors=undefined, _bsontype=ObjectID, id=VSriÆùá÷%ß8, duration=42, lyrics=, composer=, year=2015, album=, artist=, genre=, name=, $__original_save=function () {
var self = this
, hookArgs // arguments eventually passed to the hook - are mutable
, lastArg = arguments[arguments.length-1]
, pres = this._pres[name]
, posts = this._posts[name]
, _total = pres.length
, _current = -1
, _asyncsLeft = proto[name].numAsyncPres
, _asyncsDone = function(err) {
if (err) {
return handleError(err);
}
--_asyncsLeft || _done.apply(self, hookArgs);
}
, handleError = function(err) {
if ('function' == typeof lastArg)
return lastArg(err);
if (errorCb) return errorCb.call(self, err);
throw err;
}
, _next = function () {
if (arguments[0] instanceof Error) {
return handleError(arguments[0]);
}
var _args = Array.prototype.slice.call(arguments)
, currPre
, preArgs;
if (_args.length && !(arguments[0] == null && typeof lastArg === 'function'))
hookArgs = _args;
if (++_current < _total) {
currPre = pres[_current]
if (currPre.isAsync && currPre.length < 2)
throw new Error("Your pre must have next and done arguments -- e.g., function (next, done, ...)");
if (currPre.length < 1)
throw new Error("Your pre must have a next argument -- e.g., function (next, ...)");
preArgs = (currPre.isAsync
? [once(_next), once(_asyncsDone)]
: [once(_next)]).concat(hookArgs);
return currPre.apply(self, preArgs);
} else if (!_asyncsLeft) {
return _done.apply(self, hookArgs);
}
}
, _done = function () {
var args_ = Array.prototype.slice.call(arguments)
, ret, total_, current_, next_, done_, postArgs;
if (_current === _total) {
next_ = function () {
if (arguments[0] instanceof Error) {
return handleError(arguments[0]);
}
var args_ = Array.prototype.slice.call(arguments, 1)
, currPost
, postArgs;
if (args_.length) hookArgs = args_;
if (++current_ < total_) {
currPost = posts[current_]
if (currPost.length < 1)
throw new Error("Your post must have a next argument -- e.g., function (next, ...)");
postArgs = [once(next_)].concat(hookArgs);
return currPost.apply(self, postArgs);
} else if (typeof lastArg === 'function'){
// All post handlers are done, call original callback function
return lastArg.apply(self, arguments);
}
};
// We are assuming that if the last argument provided to the wrapped function is a function, it was expecting
// a callback. We trap that callback and wait to call it until all post handlers have finished.
if(typeof lastArg === 'function'){
args_[args_.length - 1] = once(next_);
}
total_ = posts.length;
current_ = -1;
ret = fn.apply(self, args_); // Execute wrapped function, post handlers come afterward
if (total_ && typeof lastArg !== 'function') return next_(); // no callback provided, execute next_() manually
return ret;
}
};
return _next.apply(this, arguments);
}, save=function wrappedPointCut() {
var args = [].slice.call(arguments);
var lastArg = args.pop();
var fn;
return new Promise.ES6(function(resolve, reject) {
if (lastArg && typeof lastArg !== 'function') {
args.push(lastArg);
} else {
fn = lastArg;
}
args.push(function(error, result) {
if (error) {
self.$__handleReject(error);
fn && fn(error);
reject(error);
return;
}
fn && fn.apply(null, [null].concat(Array.prototype.slice.call(arguments, 1)));
resolve(result);
});
self[newName].apply(self, args);
});
}, $__original_save=[function (next, options) {
// Nested docs have their own presave
if (this.ownerDocument) {
return next();
}
var hasValidateBeforeSaveOption = options &&
(typeof options === 'object') &&
('validateBeforeSave' in options);
var shouldValidate;
if (hasValidateBeforeSaveOption) {
shouldValidate = !!options.validateBeforeSave;
} else {
shouldValidate = this.schema.options.validateBeforeSave;
}
// Validate
if (shouldValidate) {
// HACK: use $__original_validate to avoid promises so bluebird doesn't
// complain
if (this.$__original_validate) {
this.$__original_validate({ __noPromise: true }, function(error) {
next(error);
});
} else {
this.validate({ __noPromise: true }, function(error) {
next(error);
});
}
} else {
next();
}
}, function (next, done) {
var Promise = PromiseProvider.get(),
subdocs = this.$__getAllSubdocs();
if (!subdocs.length || this.$__preSavingFromParent) {
done();
next();
return;
}
new Promise.ES6(function(resolve, reject) {
async.each(subdocs, function(subdoc, cb) {
subdoc.$__preSavingFromParent = true;
subdoc.save(function(err) {
cb(err);
});
}, function(error) {
for (var i = 0; i < subdocs.length; ++i) {
delete subdocs[i].$__preSavingFromParent;
}
if (error) {
reject(error);
return;
}
resolve();
});
}).then(function() {
next();
done();
}, done);
}], $__original_save=[]
CastError: Cast to string failed for value "[object Object]" at path "songs"
at MongooseError.CastError (/media/D/codebin/grep/node_modules/mongoose/lib/error/cast.js:19:11)
at SchemaString.cast (/media/D/codebin/grep/node_modules/mongoose/lib/schema/string.js:434:9)
at Array.MongooseArray.mixin._cast (/media/D/codebin/grep/node_modules/mongoose/lib/types/array.js:124:32)
at Array.MongooseArray.mixin._mapCast (/media/D/codebin/grep/node_modules/mongoose/lib/types/array.js:295:17)
at Object.map (native)
at Array.MongooseArray.mixin.push (/media/D/codebin/grep/node_modules/mongoose/lib/types/array.js:308:25)
...
As you see, the newSong that I save, has a value of a function. Can someone please point me where I am going wrong.
Your PlaylistSchema is incorrect. Take a close look at the 'songs' array - you have a type field, so mongoose interprets the schema as saying "songs is an array of Strings." Rename the type field to something like kind or set a custom typeKey and it should work.

Resources