I'm fairly new to JavaScript and am hoping someone can help me understand how to modify the function below so it will properly return a result when called. The code currently works and the handleResults function is called once the session string is generated. What I would like to do is modify the generateSessionString function so it will return the session string rather than passing it to handleResults. Can anyone give me suggestions on how I can accomplish this?
function generateSessionString(){
var cb = function (success, results){
if(!success)
alert(results);
if(results.code && results.message){
alert (results.message);
return;
}
handleResults(results);
};
var config = new KalturaConfiguration(gPartnerID);
config.serviceUrl = gServiceURL;
var client = new KalturaClient(config);
var partnerId = gPartnerID;
var userId = gUserName;
var password = gPassWord;
var expiry = gExpiry;
var privileges = gPrivileges;
var result = client.user.login(cb, partnerId, userId, password, expiry, privileges);
return result;
}
function handleResults(ks){
KalturaSessionString = ks;
}
if you like to write it in a sync way(it's still async code) you can try promise(in this example i used jQuery)
function generateSessionString(){
var dfd = new jQuery.Deferred();
var cb = function (success, results){
if(!success)
dfd.fail(results);
if(results.code && results.message){
dfd.fail (results.message);
return;
}
dfd.resolve(results);
};
var config = new KalturaConfiguration(gPartnerID);
config.serviceUrl = gServiceURL;
var client = new KalturaClient(config);
var partnerId = gPartnerID;
var userId = gUserName;
var password = gPassWord;
var expiry = gExpiry;
var privileges = gPrivileges;
client.user.login(cb, partnerId, userId, password, expiry, privileges);
return dfd.promise();
}
$.when(generateSessionString()).then(
function(session)
{
alert(session);
}
)
#Itay Kinnrot's answer is right.Actually,jQuery's on/trigger is another way to solve it,but $.Deferred is better.
if you want to know more about it,you could try to understand Pub/Sub Pattern.
This article is recommended:
http://www.elijahmanor.com/2013/03/angry-birds-of-javascript-blue-bird.html
Related
When i was writing this promise to query an sql datbase i was not testing it with require i was just running the js file straight from node in the console. Now i need it to return the data when finishing the loop and I can't figure out how. Promises as well as reading data from an SQL are both new to me so i was happy to have gotten it working. But now when i require this code with
var dbData = new getDataSQL();
it returns {} instead of a nice big chunk of data.
It finishes its promises but the data is not returned.
Any ideas on how best to return the data?
module.exports = function getDataSQL(){
//JSON OBJECTS
var dates = require('./JSON/dates.js');
var companies = require('./JSON/companies.js');
//SQL FUNCTION
var sqlConJS = require('./sqlCon.js');
function fn(retVal, i, startDate, endDate){
data[i] = JSON.parse(retVal);
var total = 0;
for(var b = 0; b<Object.keys(data[i].result).length;b++){
total = total + data[i].result[b].Amount
}
data[i].totalAmount = total;
data[i].startDate = startDate;
data[i].endDate = endDate;
console.log("No= "+i,"Reccs= " + Object.keys(data[i].result).length,"StartDate=" + startDate,"EndDate=" + endDate, "Amount = " + Math.floor(total));
dataP();
}
//INIT SQL QUERY
var data = [];
var incrDat = 0;
var dataPromise = function(i){
return new Promise(function(resolve, reject){
data[i]={};
var sqlCon = new sqlConJS(fn, dates[i].startDate, dates[i].endDate, companies[9].company, i);
if(dates.length===i)reject();
else resolve();
});
};
var dataP = function(){
dataPromise(incrDat++).then().catch(function(){
console.log("done!");
console.log(data[0].result[0]["Posting Date"]);
return data;
});
}
dataP();
}
Never mind i got it, callback function offcourse! I have so much to learn still. Add cbRetData when declaring the function at the top.
module.exports = function getDataSQL(cbRetData){
under Console.log("done!"); i put
cbRetData(data);
in the main js script we create the function cbRetData like so
function cbRetData(retData){
dbData = retData;
console.log("retData to dbData coming in!");
console.log(dbData);
}
where we call the getDataSQL function after requiring it u simply pass the function cbRetData along like so.
var getdbData = new getDataSQL(cbRetData);
I'm only just beginning to come to terms with callback functions and such.
I am writing some JavaScript codes using Parse.com.
To be honest, I have been reading how to use Promise and done lots of research but cannot still figure out how to use it properly..
Here is a scenario:
I have two tables (objects) called Client and InvoiceHeader
Client can have multiple InvoiceHeaders.
InvoiceHeader has a column called "Amount" and I want a total amount of each client's InvoiceHeaders.
For example, if Client A has two InvoiceHeaders with amount 30 and 20 and Client B has got nothing, the result I want to see in tempArray is '50, 0'.
However, with the following codes, it looks like it's random. I mean sometimes the tempArray got '50, 50' or "50, 0". I suspect it is due to the wrong usage of Promise.
Please help me. I have been looking into the codes and stuck for a few days.
$(document).ready(function() {
var client = Parse.Object.extend("Client");
var query = new Parse.Query(client);
var tempArray = [];
query.find().then(function(objects) {
return objects;
}).then(function (objects) {
var promises = [];
var totalForHeader = 0;
objects.forEach(function(object) {
totalForHeader = 0;
var invoiceHeader = Parse.Object.extend('InvoiceHeader');
var queryForInvoiceHeader = new Parse.Query(invoiceHeader);
queryForInvoiceHeader.equalTo('headerClient', object);
var prom = queryForInvoiceHeader.find().then(function(headers) {
headers.forEach(function(header) {
totalForHeader += totalForHeader +
parseFloat(header.get('headerOutstandingAmount'));
});
tempArray.push(totalForHeader);
});
promises.push(prom);
});
return Parse.Promise.when.apply(Parse.Promise, promises);
}).then(function () {
// after all of above jobs are done, do something here...
});
} );
Assuming Parse.com's Promise class follows the A+ spec, and I understood which bits you wanted to end up where, this ought to work:
$(document).ready(function() {
var clientClass = Parse.Object.extend("Client");
var clientQuery = new Parse.Query(clientClass);
clientQuery.find().then(function(clients) {
var totalPromises = [];
clients.forEach(function(client) {
var invoiceHeaderClass = Parse.Object.extend('InvoiceHeader');
var invoiceHeaderQuery = new Parse.Query(invoiceHeaderClass);
invoiceHeaderQuery.equalTo('headerClient', client);
var totalPromise = invoiceHeaderQuery.find().then(function(invoiceHeaders) {
var totalForHeader = 0;
invoiceHeaders.forEach(function(invoiceHeader) {
totalForHeader += parseFloat(invoiceHeader.get('headerOutstandingAmount'));
});
return totalForHeader;
});
totalPromises.push(totalPromise);
});
return Parse.Promise.when(totalPromises);
}).then(function(totals) {
// here you can use the `totals` array.
});
});
I've been going at a small snippet of code for like an hour or two now, but can't seem to figure out why my Javascript breaks down at the end of this code.
// Getting username from address bar and user ID from username
var siteHref = window.location.href;
var specifiedUser = siteHref.split('#');
var userName = specifiedUser[1];
var userURL = 'http://soundcloud.com/' + userName;
var idGetter = SC.get('/resolve', { url: userURL }, function(user) {
SC.get('/users/', function() {
var userInfo = new Array(3);
userInfo[0] = user.username;
userInfo[1] = user.id;
userInfo[2] = user.public_favorites_count;
console.log(userInfo);
console.log(userInfo[2]);
});
});
I've added the variables at the top for a bit of context. To explain this function passes the two parts of the array that I've specified into the console, which is perfect. Only when I call the variable is shows up as undefined?
I also tried wrapping this in an additional function and has no luck calling it.
Anyone have idea where I've gone wrong?
You are calling two asynchronous functions. The results you get in the second one are ONLY valid inside that callback function or in a function you call from there. You can't use them globally afterwards because the async functions have not yet finished yet and thus they are still undefined.
Plus, if you're asking about the userInfo variable, that goes out of scope as soon as the callback returns so it is not available anywhere else.
See the comments I added to your code:
// Getting username from address bar and user ID from username
var siteHref = window.location.href;
var specifiedUser = siteHref.split('#');
var userName = specifiedUser[1];
var userURL = 'http://soundcloud.com/' + userName;
var idGetter = SC.get('/resolve', { url: userURL }, function(user) {
SC.get('/users/', function() {
var userInfo = new Array(3);
userInfo[0] = user.username;
userInfo[1] = user.id;
userInfo[2] = user.public_favorites_count;
console.log(userInfo);
console.log(userInfo[2]);
// ** you must use userInfo here or call some other function
// ** and pass userInfo to it
});
});
// ** you cannot use userInfo here as it is both out of scope and
// ** has not yet been set
The idGetter value will contain whatever the first call to SC.get() returns which will NOT be the eventual asynchronous result. If you tell us what SC.get() is, then we might be able to help you understand what it returns.
If SC.get() is the SoundCloud function, then it appears that it returns nothing and thus that is why idGetter is undefined.
FYI, I confirmed here in the SoundCloud source that SC.get() does not return anything.
If all you're trying to do is to create a new function that contains all this code and will call a callback when the results are available, you can just define that function and then call it:
function getUserInfo(callback) {
// Getting username from address bar and user ID from username
var siteHref = window.location.href;
var specifiedUser = siteHref.split('#');
var userName = specifiedUser[1];
var userURL = 'http://soundcloud.com/' + userName;
SC.get('/resolve', { url: userURL }, function(user) {
SC.get('/users/', function() {
var userInfo = new Array(3);
userInfo[0] = user.username;
userInfo[1] = user.id;
userInfo[2] = user.public_favorites_count;
console.log(userInfo);
console.log(userInfo[2]);
// ** you must use userInfo here or call some other function
// ** and pass userInfo to it
callback(userInfo);
});
});
// ** you cannot use userInfo here as it is both out of scope and
// ** has not yet been set
}
// then, you can call it like this:
getUserInfo(function(userData) {
// you can use userData here
});
idGetter isn't a function, you can't call it. If you want it to be a function, write:
var idGetter = function () {
SC.get('/resolve', { url: userURL }, function(user) {
SC.get('/users/', function() {
var userInfo = new Array(3);
userInfo[0] = user.username;
userInfo[1] = user.id;
userInfo[2] = user.public_favorites_count;
console.log(userInfo);
console.log(userInfo[2]);
});
});
};
Then you can do idGetter() to run the function.
I can only assume that userInfo[2] is showing as undefined since it would not make since for userInfo to be undefined. If that is the case, then it is probable that user.public_favorites_count is undefined. Trying printing that out to the console, and when it shows up as undefined, you'll need to determine why that is happening. Without more information about what that object is, or the code returning that object, there's not much more help the community will be able to provide.
This seems to either be working, or is a step forward.
var idGetter = function () { SC.get('/resolve', { url: userURL }, function(user) {
SC.get('/users/', function() {
var userInfo = new Array(3);
userInfo[0] = user.username;
userInfo[1] = user.id;
userInfo[2] = user.public_favorites_count;
console.log(userInfo);
console.log(userInfo[2]);
});
});
};
var idGetter = idGetter();
Setting the variable before the function, and re-setting it after. Not sure if this is standard practise, but seems to work to some extent.
So I have this model :
'use strict';
var mongoose = require('mongoose');
var subscriberModel = function () {
var subscriberSchema = mongoose.Schema({
email: String
});
function validateEmail(email) {
var re = /^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
subscriberSchema.methods.validateSubscriber = function (subs, otherModel) {
var code = 0;
if (validateEmail(subs.email)) {
mongoose.model('Subscriber').findOne({'email': subs.email},
function(err, subscriber){
if (err) {
code = 2;
} else if (subscriber) {
code = 3;
} else {
subs.save(function(err){
if (err) {
code = 2;
}
code = 4;
});
}
});
} else {
code = 1;
}
};
return mongoose.model('Subscriber', subscriberSchema);
};
module.exports = new subscriberModel();
And I call it in another file that way :
var subscriberModel = require('../models/subscriber');
var subscriber = new subscriberModel({email: req.body.email.trim()});
var code = subscriber.validateSubscriber(subscriber, buyModel);
console.log('code = %s', code); // => displays "code = 0"
I guess it's a scope problem or something like that (because I don't use any callback -or maybe I should-) but I can't find nor the problem, nor the solution.
So, how can I get the returned code value ?
Thanks in advance.
[EDIT] : I found where the problem was and edited the code to explain it. So apparently my var is set in the callbacks of mongoose so now my question is; how do I wait for this callback to end as I need the result to display a message to the user in a webpage?
Okay so, I found the answer.
I edited my function validateSubscriber to send a callback: subscriberSchema.methods.validateSubscriber = function (subs, callback). And removed the otherModel occurences inside.
That way, when I call it in my other file I just have to do :
subscriber.validateSubscriber(subscriber, function(code){
buyModel.code = code;
console.log('code = %s', buyModel.code);
}
To get the code AND wait for the answer.
I hope it helped someone else.
Newbie question. Why is this JavaScript function returning undefined?
var redis = require("redis"), client = redis.createClient();
function generatePageUrl() {
var randomStr = randomInt.toString(32);
// Check whether this URL is already in our database;
client.smembers("url:" + randomStr, function (err, data ) {
if (data.length != 0) {
// URL already in use, try again
return getPageUrl();
}
return randomStr;
});
}
var page_url = generatePageUrl();
// add it to the database, etc
I guess it must be getting to the end and returning before it reaches the inside of client.smembers.
But I really need to check the contents of the Redis set before it returns: can I get it to return from inside the callback? If not, what can I do?
Also, advice on the way I've used this function recursively would be welcome - I'm not sure it's completely sensible :)
Thanks for helping out a newcomer.
You can't return from inside a callback. Do it like this:
var redis = require("redis"), client = redis.createClient();
function generatePageUrl(cb) {
var randomStr = randomInt.toString(32);
// Check whether this URL is already in our database;
client.smembers("url:" + randomStr, function (err, data ) {
if (data.length != 0) {
// URL already in use, try again
getPageUrl(cb);
}
cb(randomStr);
});
}
generatePageUrl(function(page_url){
// add it to the database, etc
});
If you don't like this style, you might want to consider streamlinejs - it makes you able to write your code like this:
var redis = require("redis"), client = redis.createClient();
function generatePageUrl(_) {
var randomStr = randomInt.toString(32);
// Check whether this URL is already in our database;
var data = client.smembers("url:" + randomStr, _);
if (data.length != 0) {
// URL already in use, try again
return getPageUrl(_);
}
return randomStr;
}
var page_url = generatePageUrl(_);
// add it to the database, etc