collection.fetch() does not yield me response - javascript

exports.definition = {
config : {
// table schema and adapter information
},
extendModel: function(Model) {
_.extend(Model.prototype, {
// Extend, override or implement the Backbone.Model methods
});
return Model;
},
extendCollection: function(Collection) {
_.extend(Collection.prototype, {
}); // end extend
return Collection;
}
}
When i try to do var model = Alloy.createCollection('model');
alert(appointments.fetch());
I don't get any result.

fetch is asynchronous. As so, it will return a promise, or you need to set up a callback:
appointments.fetch().done(function( r ) { console.log(r) });
Also, never use alert to debug; this is useless. Always open your console and use console.log

Related

Mocking asynchronous requests within react's getInitialState

When i created this question, my doubt was about how would i be able to test an asynchronous request utilizing mocha/enzyme/chai/sinon.
I am sure that there are different ways, but a possible one is to mock it with a handmade function that returns the appropriate values (check the answer for details).
My getInitialState method is this:
getInitialState: function() {
var me = this;
var documentData = null;
var promise = me.getDocuments();
promise.then(function(value) {
var documents = value.map(function(obj) {
return Object.keys(obj).sort().map(function(key) {
return obj[key];
});
});
documentData = documents;
});
return ({
cd: false
});
},
And the getDocuments() function that returns a promise is this:
getDocuments: function() {
var deferred = when.defer();
Collection.fetch({cd: workspaceInfo.getCD()}).then(
function(results) {
deferred.resolve(results);
},
deferred.reject
);
return deferred.promise;
},
How can i successfuly test it?
Would i have to mock the getInitialState method itself? (is that even possible)
Or just the getDocuments function with some predictable return values?
Thanks in advance, any help will be appreciated.
I solved this by requiring the Collection (which is a rest API that brings some values from a database)
var Collection = require("path/to/my/collection/Collection");
Afterwards, i use it in my getDefaultProps() method:
getDefaultProps() {
return {
Collection: new Collection()
};
},
And this in turn enables me to write tests that initialize a mocked Collection (fileDataResponse is a JSON with some data):
var CollectionMock= {
fetch: () => {
return {
then: callback => callback(fileDataResponse)
};
}
};
And use it in my test afterwards:
it("should open the modal without a loaded configuration", function() {
var instance, wrapper;
wrapper = mount(
<DocumentPreview
Collection={CollectionMock}/>
);
instance = wrapper.component.getInstance();
instance.openModal();
expect(wrapper.find('#MockedTest' + 'docOid251085').exists()).to.equal(true);
wrapper.unmount();
});

How to get Ember component object inside promise success or error call back?

I have pass two callback function success and error on promise returned from ajax call using then method. Now i am unable to get Ember component object inside success/error method.
import Ember from 'ember';
export default Ember.Component.extend({
data:null,
issueType:'',
description:null,
prepareSubmitRaiseIssueModal:function(){
var data = this.get('data');
this.set('ticket.category',data.category);
this.set('ticket.name',this.get('session.currentUser.first_name'));
this.set('ticket.phone',this.get('session.currentUser.phone'));
this.set('ticket.groupId',data.groupId);
this.set('ticket.ownerId',this.get('session.currentUser.id'));
this.set('ticket.oyoId',this.get('session.currentOwnerHotelOyoId'));
this.set('ticket.ticketRaisedBy','owner');
this.set('ticket.bookingId',data.bookingId);
this.set('ticket.subType',data.subType);
this.set('ticket.subSubIssue',data.subSubIssue);
this.set('ticket.email',this.get('ticket.oyoId')+'#oyoproperties.com');
this.set('ticket.subject',this.get('ticket.oyoId')+' : '+this.get('ticket.category'));
this.set('ticket.description',this.get('description'));
},
success:function(){
console.log(this.get('description'));
},
error:function(){
console.log(this.get('description'));
},
actions :{
submitIssue:function(){
this.prepareSubmitRaiseIssueModal();
this.get('ticket').submitRaiseIssue().then(this.success,this.error);
//this.send('closeRaiseIssueModal');
},
closeRaiseIssueModal:function(){
this.sendAction('closeRaiseIssueModal');
}
}
});
i am able to get Ember component object if instead of passing named function i pass anonymous function.
submitIssue:function(){
var self = this;
this.prepareSubmitRaiseIssueModal();
this.get('ticket').submitRaiseIssue().then(function(response){
console.log(self.get('description'));
},
function(err){
console.log(self.get('description'));
});
//this.send('closeRaiseIssueModal');
},
is there any way i can get the Ember component object's reference for former case??
Wow speaking of a spaghetti.
prepareSubmitRaiseIssueModal:function(){
var data = this.get('data');
this.set('ticket.category',data.category);
this.set('ticket.name',this.get('session.currentUser.first_name'));
this.set('ticket.phone',this.get('session.currentUser.phone'));
this.set('ticket.groupId',data.groupId);
this.set('ticket.ownerId',this.get('session.currentUser.id'));
this.set('ticket.oyoId',this.get('session.currentOwnerHotelOyoId'));
this.set('ticket.ticketRaisedBy','owner');
this.set('ticket.bookingId',data.bookingId);
this.set('ticket.subType',data.subType);
this.set('ticket.subSubIssue',data.subSubIssue);
this.set('ticket.email',this.get('ticket.oyoId')+'#oyoproperties.com');
this.set('ticket.subject',this.get('ticket.oyoId')+' : '+this.get('ticket.category'));
this.set('ticket.description',this.get('description'));
},
How about
prepareSubmitRaiseIssueModal:function(){
var data = this.get('data');
var ticket = this.get('ticket')
ticket.setProperties({
'category': data.category,
'name': ...
})
},
And to pass reference's you can either use
promise.then(function() {
this.mysuccess();
}.bind(this), function() {
this.myerror();
}.bind(this))
const self = this;
promise.then(function() {
self.blah();
});
promise.then(result => { 
this.blah();
}) 
In your case I would write a utility JS file for displaying notifications.
And handle success for each promise personally and let errors be handled in a general error method.
utils/notifications.js
function reportError(error) {
displayNotification('error', getErrorMessage(error));
}
import reportError from 'utils/notifications';
export default Ember.Controller.extend({
....
promise.then(result => {
// Do custom stuff with result;
}, reportError);
....
});
And promise within a promise
return promise1.then(x => {
return promise2.then(x2 => {
return promise3 ... etc
})
}).catch(reportError); // Single hook needed but u need to return promises

Sails.js Access Model on Service initialization

The question:
As I understand in sails.js during initialization process Services are initialized before Models.
Is there any possibility to change this behavior? To make Models load before Services.
If it's not, then how can I load particular settings from the database to use them to build instance of my class described in some Service during this Service initialization?
A little bit code for solidity:
api/models/Model.js
console.log("Model Identified");
module.exports = {
attributes: {
name: { type: 'string', required: true, size: 15 },
//Some extra secret fields
}
};
...
api/services/MyCoolService.js
console.log('service inits');
function MyCoolService(options){
//some extraordinary constructor logic may be ommited
}
MyCoolService.prototype.setOptions = function(options){
//Set values for MyCoolService fields.
}
//Some other methods
var myCoolServiceWithSettingsFromDb = new MyCoolService();
//That's the place
model.findOne(sails.config.myApplication.settingsId).exec(function(err,result){
if(!err)
myCoolServiceWithSettingsFromDb.setOptions(result);
});
module.exports = myCoolServiceWithSettingsFromDb;
It's because you instantiate object in service with constructor that needs sails that not exist. Try use this at MyCoolService;
module.exports = {
someOption: null,
method: function () {
var that = this;
sails.models.model.findOne(sails.config.myApplication.settingsId)
.exec(function (err, result) {
if (!err)
that.someOption = result;
});
}
};
that method can be called by sails.services.mycoolservice.method() or simply MyCoolService.method() to give your service some option from DB.
If you want to initiate them at Sails start, call that method at config/bootstrap.js
Thanks to Andi Nugroho Dirgantara,
I ended up with this solution (I still don't like it much, but it works):
api/services/MyCoolService.js
console.log('service inits');
function MyCoolService(options){
//some extraordinary constructor logic may be ommited
}
//All the same as in question
//The instance
var instance;
module.exports = module.exports = {
init: function(options) {
instance = new MyCoolService(options);
},
get: function() {
return instance;
},
constructor: MyCoolService
};
config/bootstrap.js
...
Model.findOrCreate({ id: 1 }, sails.config.someDefaultSettings).exec(function(err, result) {
if (err)
return sails.log.error(err);
result = result || sails.config.someDefaultSettings;
MyCoolService.init(result);
return sails.log.verbose("MyCoolService Created: ", TbcPaymentProcessorService.get());
});
...
tests/unit/service/MyCoolService.test.js
...
describe('MyCoolService', function() {
it('check MyCoolService', function(done) {
assert.notDeepEqual(MyCoolService.get(), sails.config.someDefaultSettings);
done();
});
});
...
It works: the service is instantiated once while bootstraping and it's instance is avaliable everywhere.
But to me this solution still weird... I still don't understand how to globally instantiate instance of my service (for use in a lot of controllers) and make it the best way.

angular controller is executing before factory complete

I have moved some common code to factory. but the controller is executing before factory get loaded. In this case i am getting the blank response(zero results)
can anyone suggest the best solution.
here is my angular factory,
app.factory('TabsFactory', function($resource){
var activetabs = {};
activetabs.getDepositAccountDetails = function() {
return $resource('xxxx/:number', {}, {
getDepositAccountDetailsService: {
method: 'GET',
isArray: false
}
});
}
activetabs.getAccountInfo = function(){
return accountinit.accountInfo;
}
activetabs.setAccountInfo = function(accountnumber, result) {
var accountinit = {
accountInfo: []
}
if (result.code == "v") {
activetabs.getDepositAccountDetails().getDepositAccountDetailsService({
number: accountnumber
}).$promise.then(function(response) {
accountinit.accountInfo = response;
//here i am getting the JSON response
}, function(error) {
});
}
return accountinit;
}
return activetabs;
});
controller,
TabsFactory.setAccountInfo(accountnumber, $scope.accountInfo);
$scope.accountInfo = TabsFactory.getAccountInfo();
alert(JSON.stringify($scope.accountInfo));
You should use chain promise to update scope variable, because your accountInfo variable is updated inside $resource promise.
Code
TabsFactory.setAccountInfo(accountnumber, $scope.accountInfo).then(function(data){
$scope.accountInfo = TabsFactory.getAccountInfo();
alert(JSON.stringify($scope.accountInfo));
});
Update
Service method should return promise inorder to continue promise chain
activetabs.setAccountInfo = function(accountnumber, result) {
var accountinit = {
accountInfo: []
}
if (result.code == "v") {
//added return below
return activetabs.getDepositAccountDetails().getDepositAccountDetailsService({
number: accountnumber
}).$promise.then(function(response) {
accountinit.accountInfo = response;
return accountinit.accountInfo;
//here i am getting the JSON response
}, function(error) {
});
}
return accountinit;
}
Yes, this will happen because of JavaScript executing asynchronous operations but your controller in such a way that it expects things to be synchronous operations.
When you call TabsFactory.getAccountInfo() its possible that your $resource('xxxx/:number') is still not completed and response ready for you to process!!
So, what to do? You have make use of promise. I usually have a repository (A factory with method that return promise) to handle server communications. Here is an example:
app.factory('accountRepository', ["$http","$q",function($http,$q){
return {
getDepositAccountDetails : function(id) {
var deferred = $q.defer();
$http.ger('xxx').success(deferred.resolve).error(deferred.reject);
return deferred.promise;
}
};
}] );
My repository will have more operations like add account, update account info etc..
my controller/service then calls these methods as follows:
accountRepository.getDepositAccountDetails(123).then(function(response) {
// Process the response..
}, function(error) {
// Some error occured! handle it
});
doing so, my code gets executed only after I get response from server and data is ready for consumption or display. Hope this helps..
Update: You might want to have a look at this to get the idea ;)

How to prevent collection of removing model when destroyed?

Is there a way to prevent backbone.js collection of removing my model when it gets detroyed?
Everytime it happens I receive a "remove" trigger event from collection
collection.on("remove", this.handleRemove)
already tried passing some arguments but nothing
model.destroy({silent: false, remove: false})
The solution is to override the Backbone model destroy function. I made this on an abstract model with success and callback strategy:
Parameter "data" corresponds to the original parameter "resp".
destroy: function(successCallback, errorCallback)
{
var options = { wait: true };
var model = this;
successCallback = successCallback || function() {};
errorCallback = errorCallback || function() {};
var destroy = function()
{
model.trigger('destroy', model, model.collection, options);
};
options.success = function(data)
{
if ('SUCCESS' === data.responseCode)
{
if (options.wait || model.isNew())
destroy();
successCallback(data);
if (!model.isNew())
model.trigger('sync', model, data, options);
}
else
{
errorCallback(data);
}
};
if (this.isNew())
{
options.success();
return false;
}
var xhr = this.sync('delete', this, options);
if (!options.wait)
destroy();
return xhr;
}

Categories

Resources