JavaScript random item from an imported array behaving strangely - javascript

The following code seems to be behaving strangely. Basically, I'm importing a list of line-separated sentences from a text file, then making an array out of them. But when I try to choose a random sentence from the array, it doesn't work because sentenceString becomes undefined.
However, when I run
Math.floor(Math.random() * (sentenceArr.length) + 1);
I get a nice random number as expected.
And when I run sentenceArr.length
I get the number 12, which is indeed the length.
What am I missing?
var sentenceArr = [];
$.get('sentences.txt', function(data){
sentenceArr = data.split('\n');
});
var rand = Math.floor(Math.random() * (sentenceArr.length) + 1);
var sentenceString = sentenceArr[rand];
var sentence = sentenceString.split(' ');
Update:
I tried making a Promise as suggested below, but it still doesn't seem to be working. My new code with the Promise looks like this:
var sentenceArr = [];
var done = false;
function loadSentences() {
var rand = Math.floor(Math.random() * (sentenceArr.length) + 1);
var sentenceString = sentenceArr[rand];
var sentence = sentenceString.split(' ');
};
$.get('/sentences.txt', function(data){
sentenceArr = data.split('\n');
done = true;
});
var isItDone = new Promise(function(resolve) {
if(done) {
resolve('it worked');
}
});
//consume the promise:
var checkIfDone = function() {
isItDone
.then(function (fulfilled) {
loadSentences();
})
.catch(function (error) {
console.log('oops, it failed');
});
};
checkIfDone();
This seems to always return "oops, it failed", as if the promise is never fulfilled. However, when I check the value of "done", it is "true", meaning the Ajax request was completed before moving on to the next steps. Could anyone enlighten me? I've read three tutorials on promises already, and can't seem to figure out my error in applying the concept to my own code. Thank you.

The problem is you are trying to manipulate the file content before the response of server be complete.
Take a look at promises to understand more https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
And the way to solve your question using jquery ajax api.
var sentenceArr = [];
var file = 'path/to/file';
$.get(file)
.done(function (data) {
sentenceArr = data.split('\n');
var rand = Math.floor(Math.random() * (sentenceArr.length) + 1);
var sentenceString = sentenceArr[rand];
var sentence = sentenceString.split(' ');
console.log(sentenceArr)
console.log(rand)
console.log(sentenceString)
console.log(sentence)
});

Thanks, I solved the issue by first wrapping everything in a function, and using .then() to run everything only after the Ajax "get" was completed:
var sentenceArr = [];
const getData = () =>
$.get('http://eslquiz.net/wordmix/sentences.txt', function(data){
})
.then(data => { // use this format to run function only after json get is done (since it's async)
// "data" is the contents of the text file
sentenceArr = data.split('\n');
console.log('Made sentence array');
loadSentences();
});

Related

How to break out of promise in Javascript

I have develop a command line programm and its working, but when its done it doesnt finished. i have to control+c an shell to exit
Im new at javascript. Must i divine a callback to say the programm that its done?
My Code:
importer.then(function (csvData) {
var mySqlConnection = new MySqlConnection(config['phpipam-db']['host'], config['phpipam-db']['user'], config['phpipam-db']['password'], config['phpipam-db']['database']);
var connection = mySqlConnection.getConnection();
mySqlConnection.selectSubnets(connection).then(function (customerFolders) {
var ipv6Data = manager.getIpv6CustomerSubnetsInsertData(csvData, customerFolders);
var ipv4Data = manager.getIpv4CustomerSubnetsInsertData(csvData, customerFolders);
mySqlConnection.insertIpv6Subnets(ipv6Data);
});
});
Add console.log statements after var connection = mySqlConnection.getConnection(); and mySqlConnection.insertIpv6Subnets(ipv6Data);.
If they are executed, the problem is not in the code you posted.
If they are not, you have to check whether your promises get fulfilled.
Are this methods: manager.getIpv6CustomerSubnetsInsertData, mySqlConnection.insertIpv6Subnets also returning promises?
If you modify your code like this, can you see Done in the console?
importer.then(function (csvData) {
var mySqlConnection = new MySqlConnection(config['phpipam-db']['host'], config['phpipam-db']['user'], config['phpipam-db']['password'], config['phpipam-db']['database']);
var connection = mySqlConnection.getConnection();
return mySqlConnection.selectSubnets(connection).then(function (customerFolders) {
var ipv6Data = manager.getIpv6CustomerSubnetsInsertData(csvData, customerFolders);
var ipv4Data = manager.getIpv4CustomerSubnetsInsertData(csvData, customerFolders);
return mySqlConnection.insertIpv6Subnets(ipv6Data);
}).then(function () {
console.log('Done');
});
});

Return an object when the promise finishes inside a require

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.

How to properly use Parse / Promise?

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.
});
});

cloud code in parse.com doesn't work to all data

I just start learning how to modify my database in Parse.com. I'm using cloud code in my mac.
In my database, I got around 150 data, with class openhour and closehour. Unfortunately, it was written in string. It's structure is like this 12:30.
I want to convert all of it from string to number, and store it in class openHour and closeHour. For an example, I will change 12:30 as string, to 12.5 as number.
I've wrote this code, deploy it, and execute it using terminal in mac. It seems succeeded since I can see some of my data in class openHour and closeHour are being filled.
My problem is, there are several data that are still empty. Can someone show me why this is happening? did I miss something?
var _ = require('underscore.js');
Parse.Cloud.define("openclose", function(request, response) {
Parse.Cloud.useMasterKey();
var query = new Parse.Query("Places");
query.limit = 1000;
query.find().then(function(results) {
_.each(results, function(result) {
var openString = result.get("openhour");
var openHourString = openString.slice(0,2);
var openHour = Number(openHourString);
var openMinuteString = openString.slice(3);
var openMinute = Number(openMinuteString);
result.set("openHour", openMinute/60 + openHour);
var closeString = result.get("closehour");
var closeHourString = closeString.slice(0,2);
var closeHour = Number(closeHourString);
var closeMinuteString = closeString.slice(3);
var closeMinute = Number(closeMinuteString);
result.set("closeHour", closeMinute/60 + closeHour);
});
return Parse.Object.saveAll(results);
}).then(function(results) {
response.success(results);
}, function(error) {
response.error(error);
});
});
Try adding a "return" before before the query.find()
return query.find().then(function(results) {
Also - I assume you have < 1,000 rows of data? Otherwise, you will need to make this recursive because of the max query limit.

Trouble using Breeze offline data getting undefined is not a function

Am having trouble using offline data with breeze, Most functions work fine while online.
Then an error undefined is not a function arise in the function i guess when calling this fuction
$scope.getPagedDataAsync = function (pageSize, page, searchText) {
var skip = (page - 1) * pageSize;
var take = pageSize * 1;
app.dataservice.getCustomerPage(skip, take, searchText)
.then(customersQuerySucceeded);
};
Here is the modified getCustomerPage function to work offline
function getCustomerPage(skip, take, searchText) {
var importData = window.localStorage.getItem(stashAll);
manager2.importEntities(importData);
var query = breeze.EntityQuery
.from("Customers")
.orderBy("CompanyName")
.skip(skip).take(take)
.inlineCount(true);
if (searchText) {
query = query.where("CompanyName", "contains", searchText);
}
return manager2.executeQueryLocally(query);
}
And Here is how i declared manager2 for offline usage
var manager2 = new breeze.EntityManager();
And here is customersQuerySucceeded function where i think error arise, i works fine while online on the samples.
function customersQuerySucceeded(data) {
$scope.offlinecustomers = data.results;
if (data.inlineCount) {
$scope.totalServerItems = data.inlineCount;
}
$scope.$apply();
app.logger.info("Fetched " + data.results.length + " Offline Customers ");
}
Here is how i got data offline on the first place.
manager = new breeze.EntityManager(serviceName);
var query=breeze.EntityQuery
.from("Customers");
manager.executeQuery(query);
var exportData = manager.exportEntities();
window.localStorage.setItem(stashAll, exportData);
It turns out executeQueryLocally returns an data while executeQuery returns a promise,
The error was because i was referring to properties on a promise.
I guess i have to rewrite my code to account that...

Categories