get: function (code) {
console.log('Retrieving model for code : ', code);
let database = UTILS.getDatabase('databaseName');
return database.models.modelName.find({})
.then(function (users) {
console.log(' ----------- ', users);
return users;
})
.catch(function (error) {
return '{success: "false", msg: "Error found : ' + error + '"}';
});
}
This code is running without any errors, but the function that calls "get" couldn't find any record, while callback function prints around 8-9 records in console. I know this is callback functionality, but I need this to be happen sequentially.
I also tried to use yield return yield database.models.modelName.find({}) with * function, but getting {}, an empty object.
Please suggest a way to avoid callback and get data from mongodb.
Thanks Julien, but I can't use callback, because the function which is calling "get" has logic to process object return from mongoose.
Hi Ravi, here is complete flow of this process stack. Route -> Controller -> Facade -> Service -> Dao (the code I posted is belongs to Dao layer get function)
This looks typical typed language solution, but I need this to be in this way.
a Service layer function could collect data from multiple model and could be processed collectively, so callback process doesn't fulfill my requirement here.
I am completely stuck, Thanks for help :)
Router :
app.route('/nodics/users')
.get(CONTROLLER.UserController.get)
.post(CONTROLLER.UserController.set);
Controller:
get: function (request, response, error) {
let users = FACADE.UserFacade.get();
response.json(users);
}
Facade :
get: function (code) {
console.log('inside Facade call....', code);
return SERVICE.UserService.get(code);
}
Service :
get: function (code) {
console.log('inside Service call....', code);
return DAO.UserDao.get(code);
}
Dao method is already there at top. This is a sample layered implementation. but I just want to to be implemented in this way only. so that I can call, DAO layer method anytime and from anywhere in the Service layer.
Use Case:
1. I want to add one item into cart, so I pass, PID, SKUID and quantity to the router, which simply pass controls to controller.
2. Controller pass it to facade and Service.
3. In service layer
1. Call another service to check if quantity is valid
2. Call DAO to load product item
3. Call another DAO to load Inventory (or use from first call)
4. Call another DAO to load price item, based on local and currency, or other parameters.
5. Finally load ORDER and add this item into it and save it
6. Return order item to facade layer
4. In Facade, apply filter to return only fields required to expose as service.
So If I want to implement this use case, getting data by callback from mongoose will not help.
So please suggest me the way to get data directly from mongoose without using callback.
You need to pass a callback to your function and call it from your promises:
get: function (code, cb) {
console.log('Retrieving model for code : ', code);
let database = UTILS.getDatabase('databaseName');
return database.models.modelName.find({})
.then(function (users) {
console.log(' ----------- ', users);
cb(users);
})
.catch(function (error) {
cb({success: "false", msg: "Error found : ' + error + '"});
});
}
Related
If I try to call a get on my nodeJS than it's work but I get different values.
I have to submit my search parameters 1-3 times to get the right output.
My Node server get the right search parameter and output the right API response but if I want to print it to my Angular app then it will use a old parameters. I don't understand the behavior.
Request Path:
angular -> nodeJS -> 3rd partie API -> nodeJS -> angular
Is that path wrong? how can I get the current data for angular?
APP.JS
app.get('/url', (req, res) => {
var name = req.query.searchname;
console.log("Output\n---------------------------")
console.log(req.query.searchname);
doGetRequest(name);
return res.send(data);
})
test.service
test(searchName){
this.http.get<any>('http://localhost:3000/url', {
params: {
searchname: searchName
}}).subscribe(data => this.totalAngularPackages = data)
this.log();
}
log(){
console.log(this.totalAngularPackages);
}
The variable this.totalAngularPackages is assigned asynchronously. Any statements that directly depend on it must be inside the subscription. By the time the console.log is run, the variable this.totalAngularPackages is still undefined or holds the previously assigned values. You could learn more about async requests here.
test(searchName) {
this.http.get<any>('http://localhost:3000/url', {params: {searchname: searchName}})
.subscribe(data => {
this.totalAngularPackages = data;
this.log(); // <-- must be inside the subscription
});
}
log() {
console.log(this.totalAngularPackages);
}
Up until now for me the concept of a Node Worker has been one of those things that sounds interesting and I will find out about one day.
Well that day has come and I am asking for some help.
I need to call a web service and then process the data returned. I can call the service with an XMLHttpRequest, but then I have to get useful data out of it.
There is a nice node module that both calls the service and returns the data in a useful form with one call.
I can set up Node worker (in Wakanda) to do this and verify that it works.
My problem is handling the asynchronous call in the proxy.
The call to the node module looks like this:
myModule.getData(param, (err, data) => {
// data is an object containing everything I want.
// if I get data I want to return it to the proxy
// if I get an err I want to return the error to the proxy
});
So my wrapper code looks something like this:
function doSomething(param){
// call proxy with param
// wait for result
// return result
}
This all sounds like something I should know how to do. However I think I am struggling with too many new things and getting myself absolutely confused.
PS: I did try Threadify but couldn't work out how to get the worker to return the error it received.
I would really appreciate any help or pointers here.
If I am correctly understanding your issue, you cannot return a value from a function AFTER an asynchronous call completes. You need to handle the data within the myModule.getData callback.
If you would rather handle it in a calling function (like doSomething), you can use a promise to "return" a value.
function myProxy(param) {
return new Promise((resolve, reject) => {
myModule.getData(param, (err, data) => {
if (!err) { // or however you determine an error occurred.
resolve(data); // if I get data I want to return it to the proxy
} else {
reject(err); // if I get an err I want to return the error to the proxy
}
});
});
}
function doSomething(param){
myProxy(param).then(data => {
// Handle the data here.
}).catch(err => {
// Handle the error here.
});
}
I'm calling a server method from my client side code via the Meteor.call() function.
But I get an undefined value when I try to pass the callback function's return value to a var within the onCreated function.
Looking at this solution the result is still only available within the scope of the callback:
https://stackoverflow.com/a/31661065/1829251
Also when I read the docs for Meteor-call it explains that the method is async which explains that the return value of the function can't be assigned to a variable:
https://docs.meteor.com/api/methods.html#Meteor-call
Question:
How can you return a result from Meteor.call method in client?
Code snippet of client side code:
import { Template } from 'meteor/templating';
import { Meteor } from 'meteor/meteor';
import { Datasets } from '../../../../api/datasets/datasets.js';
import { Constants } from '../../../../startup/constants.js';
import './rollup-history.html';
import './rollup-history.scss';
Template.rollup_history.onCreated(function() {
this.historyDays = 7;
this.rollupHistoryMECTitles = () => {
let mecObjects = [];
// Query the MEC calendar dates from AppConfiguration collection
let method = Constants.Methods.getAppConfigCollectionFromKeyDateSorted;
mecObjects = Meteor.call(method, Constants.AppConfigKeys.meccalendarInitialValues, this.historyDays, (error, result) => {
if(error){
console.log("Error retrieving MEC Dates" + error);
}
//Logging values here shows the values as expected
console.log("MEC Dates in View" + JSON.stringify(result));
return result;
}
);
//logging value here shows undefined value
console.log("mec objects: " + JSON.stringify(mecObjects));
return mecObjects;
};
});
Template.rollup_history.helpers({
mecHeaderColumns: function() {
return Template.instance().rollupHistoryMECTitles();
},
});
Because the return statement is in the callback and is unblock you can't return a method value like that. you can put it https://github.com/stubailo/meteor-reactive-method which will return the value but it must live inside a helper or reactive environment.
short answer:
define your Meteor.Method inside common code (code available to server and client) then use Meteor.apply with the option { returnStubValue : true }
mecObjects = Meteor.apply(method, [Constants.AppConfigKeys.meccalendarInitialValues, this.historyDays], { returnStubValue: true }, (error, result) => {
if(error){
console.log("Error retrieving MEC Dates" + error);
}
//Logging values here shows the values as expected
console.log("MEC Dates in View" + JSON.stringify(result));
return result;
}
);
console.log(mecObjects) //prints the client-side result of the meteor method
longer answer:
Meteor allows for Optimistic-UI which is simulating a server method on the browser. To enable this, define your Meteor.Method in common code (server + client space). This is useful because the user can see the UI updates faster since we don't need to make a server-round trip.
Notice that in the picture above, the method call runs first on the client and later on the server. { returnStubValue: true } allows the caller to receive the method's return value from the client run
When writing a Meteor method, you can use this.isSimulation to specify what logic runs exclusively on client or server. Any code outside of this check runs in both.
Note that in the picture above that the server only runs console.log("hi i'm server") while only the browser runs console.log("hi i'm client"). Both run the code outside of the isSimulation check.
A few concerns:
What if the server return value is different from the client return value?
result != mecObjects so you will need to handle that situation properly.
What if the client run fails? Does the server still run?
Yes, the server still runs. However you can prevent server runs on client
failures by adding another option, throwStubExceptions: true. This option will
throw client exceptions which you can capture in a try catch.
What if the client and server mongo updates are different?
The server mongo changes override the client mongo changes.
see more at
https://guide.meteor.com/methods.html and https://forums.meteor.com/t/how-to-return-value-on-meteor-call-in-client/1277/2
The value of your mecObjects will always be undefined, because Meteor.call function doesn't return anything. Server's method call response (or error) will be passed to callback only, like in your code, actually: those error and result variables.
I'm building a small API that fetches data and perform tasks on it (using async), stores some of this data in an array using push, and then shows it to a client with Hapi's reply().
I'm looking to empty my array (for example using arrayname.length = 0) right after the server has sent an answer to the client.
Current code follows this logic:
let data = []
server.route({
method: 'GET',
path: '/api/{data}',
handler: function (request, reply) {
async.parallel([
function(callback) {
// fetch some data, work with it and then add it to our array using push
data.push ({ // example data
bla:'blabla',
number:'10'
});
callback();
},
function(callback) { // another time (...)
data.push ({
bla:'blabla',
number:'2'
});
callback();
}
],
function(err) { // This is the final callback, sort data and send it using reply
data.sort(function (a, b) {
return a.number - b.number
})
reply(data)
console.log(request.params.data)
})
}
});
server.start((err) => {
if (err) {
throw err;
}
console.log(`Server running at: ${server.info.uri}`);
});
With the current code if I refresh my page, data gets added to the already existing data array.
I tried for several hours and find no way to empty this array right after reply(data) has been called.
Is there any way to do that, or would I have to nest my parallel async functions with an async serie and perform the emptying that way? (Haven's been able to succeed either + sounds overkill).
Is there a way to simply execute something once "reply" has been called or when there is a new "get" so that each client can have the only the data generated by it's request and not also the data that was in the array before?
Thanks!
I'm in agreement with all of the answers suggesting to put the array within the handler. With the array situated out side of the request handler, all request coming through will be writing to the same array. Even if you clear this array at the end of your handler logic, it is not guaranteed to be empty for the next request context since you can have many request context in play.
Following #piotrbienias's advice I created the array inside handler rather than at the beginning of my file and it's cleared each time I do a new request on my API, so I don't need to empty it once the reply is sent.
Thanks, #piotrbienias!
I am trying to get data from json data so i write this:
app.factory('data', function($resource) {
return $resource('mock/plane_urls.json', {}, {
getTreeData: { method: 'GET', isArray: false }
})
})
and then using:
data.getTreeData.Carriers.Carrier;
Where Carriers is the first node in json file. but it doesnt work ;/ I got error
Error: data.getTreeData.Carriers is undefined
You are trying to reach into the Carriers object before it is fetched. Before the data comes back, Carriers is just an empty object.
You could do something like $scope.carriers = data.getTreeData(); and then in your view have an element with ng-repeat="carrier in carriers"
The idea behind $resource is that you get an empty object, so the view renders nothing. When the request is complete, the empty object is replaced and the view is re-rendered with the data automatically.
You could also use the $http service like so and provide a callback function that executes once the data is fetched.
$http.get('mock/plane_urls.json').then(function(data){
carrier = data.Carriers.Carrier
});
BUT! should break this into a service and a controller though. Just have the service getTreeData return the promise object like so: return $http.get('mock/plane_urls.json'); and then in your controller call it with then() and provide the callbacks for success and error:
getTreeData.then(
function(data){
carrier = data.Carriers.Carrier;
},
function(err){
console.log("Error: " + err);
});
You can use $scope.$watch to watch the value of the data.getTreeData.
When new data comes in, the callback will be called, then, you can get your data you want.
http://docs.angularjs.org/api/ng.$rootScope.Scope