Waiting for Several CSV files to load with Papaparse - javascript

I have been trying to load several CSV files before running the code on my page as it uses the data from the CSV files. I have used PAPAPARSE.js as a library to help me with this and I have come up with the following solution.
function loadData(){
console.log("Loading Data!")
loadNodeData();
loadEdgeData();
loadHeadendData();
setup();
}
function loadNodeData(){
Papa.parse("Data/CSV1.csv", {
download: true,
step: function(row) {
NodeData.push(row.data)
},
complete: function() {
console.log("Loaded Node Data!");
load1 = true;
}
});
}
function loadEdgeData(){
Papa.parse("Data/CSV2.csv", {
download: true,
step: function(row) {
EdgeData.push(row.data)
},
complete: function() {
console.log("Loaded Edge Data!");
load2 = true;
}
});
}
function loadHeadendData(){
Papa.parse("Data/CSV3.csv", {
download: true,
step: function(row) {
HeadendArr.push(row.data)
},
complete: function() {
console.log("Loaded Headend Data!");
load3=true;
}
});
}
function setup() {
intervalID = setInterval(isDataLoaded,100)
}
function isDataLoaded(){
//Attempt to setup the page, this will only work if the data iss loaded.
if(load1 && load2 && load3){
console.log("LOADED");
_setupSearchOptions();
}
}
I have this following setup, however i don't know if this is the best way to go about doing something like this. the loadData triggers on page load
<head onload="loadData()">
Is this the correct way to make the program flow?

A more modern approach is to use promises.
You can cut down the code repetition by creating one function that passes in the url and step array to push to and wrap the Papa.parse() call in a promise that gets resolved in the complete callback.
Then use Promise.all() to call _setupSearchOptions() after all three promises resolve
Something like:
function parseCsv(url, stepArr){
return new Promise(function(resolve, reject){
Papa.parse(url, {
download:true,
step: function(row){
stepArr.push(row.data)
},
complete: resolve
});
});
}
function loadData(){
const nodeReq = parseCsv("Data/CSV1.csv", NodeData);
const edgeReq = parseCsv("Data/CSV2.csv", EdgeData);
const headReq = parseCsv("Data/CSV3.csv", HeadendArr);
Promise.all([ nodeReq, edgeReq, headReq]).then(_setupSearchOptions);
}
Note that no error handling has been considered here. Presumably the Papa.parse api also has some fail or error callback that you would use to call the reject() and use a catch() with Promise.all() to handle that failure

Related

Abort upload with UIkits Upload Component?

The title says it all. How can I abort the upload with UIKits Upload Component?
I'm trying to abort the upload in the beforeAll callback but I can't seem to get it to work.
UIkit.upload('.js-upload', {
url: '',
multiple: false,
mime: 'audio/*',
allow: '*.mp3',
beforeAll: function () {
return false; // <--- Why does it not return/abort?
});
}
});
Have a look at the source code. The return value from beforeAll isn't used.
The best option I see to abort the request is to get hang of the XMLHttpRequest object and call abort() on it:
UIkit.upload(".js-upload", {
// ...
loadStart: function (e) {
e.target.abort();
},
abort: function (e) {
// clean up after abort
}
// ...
});

Promise + jQuery Ajax chain makes memory grow. Am I using them correctly?

I have a JS that must perform a remote operation periodically, then react to it. The worflow is:
- Start the operation in main script
-> `setInterval` calling a function every 5 seconds
-> This function waits for a `Promise` that internally...
-> ... calls `$.ajax`, validate the response, then resolve or reject.
I'm seeing memory growing in my app and this operation chain may be the cause. Am I using Promises the right way?
The main entry point is simply:
StateWatcher.startWatchSystem();
Then the involved modules:
var StateWatcher = {
// is called by the main app to start the backround check every 5 sec
// the actual function that performs the update is "doSystemStateUpdate"
startWatchSystem: function() {
this.doSystemStateUpdate();
this.systemWatchTimeout = setInterval(() => {
this.doSystemStateUpdate();
}, 5000)
},
<...>
// this is "doSystemStateUpdate": the remote call is performed by another module "RemoteQuery.getSystemState()".
// that last function returns a Promise (see below), so I can check the result with "then" and "catch"
doSystemStateUpdate: function() {
RemoteQuery.getSystemState()
.then((data) => {
// ok, got the new State
this.currentSystemState = data.Message;
// ... inform other modules etc etc...
})
.catch((error) => {
Logger.write("error", "doSystemStateUpdate:");
Logger.write("error", error);
});
}
}
Here is the "RemoteQuery" module:
var RemoteQuery = {
connectionError: false,
// the getSystemState internally calls jQuery AJAX but then enclose it in a Promise
// When Ajax finishes, before actually resolve the promise it must do a quick check on the Ajax result, using function "validateResponse"
getSystemState: function () {
return new Promise((resolve, reject) => {
$.ajax({
dataType: "json",
url: <.... http...>,
method: "GET",
cache: false,
success: function(data) { RemoteQuery.validateResponse(true, resolve, data) },
error: function(xhr, opts, error) { RemoteQuery.validateResponse(false, reject, xhr) }
});
})
}
<...>
// this is the last step: this function sets an "alarm" flag if the ajax operation was not ok.
// at the end, it calls the function to resolve the promise
validateResponse: function(ok, then, args) {
if (this.connectionError == false && ok == false) {
this.connectionError = true;
// do other stuff (logging,...)
}
else if (this.connectionError == true && ok == true) {
this.connectionError = false;
// do other stuff (logging,...)
}
then(args); // now resolve or reject based on how it has been called after ajax->success or ajax->error
},
}

Nightwatch correct way to get api result to populate variable then run tests that use that variable

I am new to node and the async way of doing things.
I want to create and run a test suite using nightwatch.js, I have read all the docs and I'm baffled at how to do what I want (been working on it for 3 days already).
Am I thinking about this the wrong way?
module.exports = {
before: function(browser) {
/*
Here I just want to make a web call to an api and get a result and then
store that result in a variable which we will use later in test1 and other test cases
*/
browser.globals.myVariable = resultofsomeapicalll;
//wait here until proceeding
},
after: function(browser) {
browser.end();
},
beforeEach: function(browser) {
},
afterEach: function() {
},
'test1': function(browser) {
browser.url(browser.launchUrl + browser.globals.myVariable, function(result) {
browser.waitForElementPresent('body', 1000);
browser.expect.element("#something").to.be.present;
browser.saveScreenshot('./screenshots/' + browser.currentTest.module + '/' + browser.currentTest.name + '.png');
});
},
};
To perform asynchronous task in the Nightwatch.JS before[Each] or after[Each] hooks, you need to pass an callback argument to the function, which you trigger once the job is done.
In below example, it would be an API Call using Axios library;
module.exports = {
before: function(browser, done) {
axios.get('https://example.com/api?ID=12345')
.then(function (response) {
browser.globals.myVariable = response;
done();
})
.catch(function (error) {
done(error);
});
},
after: function(browser) {
browser.end();
},
beforeEach: function(browser) {
},
afterEach: function() {
},
'test1': function(browser) {
console.log()
},
};
Controlling the done invocation timeout
By default the done invocation timeout is set to 10 seconds (2 seconds
for unit tests). In some cases this might not be sufficient and to
avoid a timeout error, you can increase this timeout by defining an
asyncHookTimeout property (in milliseconds) in your external globals
file (see below for details on external globals).
http://nightwatchjs.org/guide/#asynchronous-before-each-and-after-each-
Best regards,
Riku

Clearing setTimeout when $http call is in pending

function getDBCounts() {
$http.get('URL')
.then(function (response){
$scope.stats = response.data;
$scope.getDBCountsTimeOut = setTimeout(getDBCounts, 5000);
}, function () {
$scope.getDBCountsTimeOut = setTimeout(getDBCounts, 5000);
})
}
$scope.$on("$destroy", function () {
clearTimeout($scope.getDBCountsTimeOut);
});
when ever I am going to different controller I am making sure I am cancelling all timeouts but the issue is when the $http call is in pending and I am moving to different controller at the same time (the timeout is not being created until we get the response) and I am unable to cancel that timeout on controller change since the call is in pending state and I cannot clear a timeout which is not been created.
How do I handle this situation. what is the best solution for this issue.
I have done this but in the error section I am unable to differentiate the network error and cancelled timeout because I need to still call setTimeout if it is network error.
$scope.canceler = $q.defer();
function getDBCounts() {
$http
.get(apiUri + '/backend/database/stats', {timeout: $scope.canceler.promise})
.then(function (response){
$scope.stats = response.data;
$scope.getDBCountsTimeOut = setTimeout(getDBCounts, 5000);
}, function (er, second) {
$scope.getDBCountsTimeOut = setTimeout(getDBCounts, 5000);
})
}
$scope.$on("$destroy", function () {
clearTimeout($scope.getDBCountsTimeOut);
$scope.canceler.resolve();
});
For both network error and timeout i get this as a response:
{config: Object
data: null
headers: (name)
status: 0
statusText: ""}
Now how do I resolve this issue.
Thanks in advance.
This seems to be a limitation of the $http API. I would also have expected that you can tell from the response/error, whether the request has timed out.
The only way I see here is that you don't cancel the promise but set a flag in the scope when it has been destroyed. Then you simply don't set the timeouts when the scope has already been destroyed:
function getDBCounts() {
$http.get('URL')
.then(function (response){
$scope.stats = response.data;
})
.finally(function() {
if (!$scope.destroyed) {
$scope.getDBCountsTimeOut = setTimeout(getDBCounts, 5000);
}
})
}
$scope.$on("$destroy", function () {
clearTimeout($scope.getDBCountsTimeOut);
$scope.destroyed = true;
});
Your approach is better and would be the "correct" way. However, it seems this is not possible.
PS: If you want to do something regardless of whether a promise has been resolved or rejected, you should use finally (see above). Please note that in older browser (and thus older JS/ECMA-Script versions) finally is a reserved word. If you want to make sure that older browsers are supported, call it like this:
$http.get(...)["finally"](function() {
})

How to run second function after the first has ended in javaScript?

function addItemToCart (id_1, id_2, id_3, id_etc) {
jQuery.ajax({
});
}
function clearCart()
{
jQuery.ajax({
});
}
function buyButton()
{
clearCart();
setTimeout(function()
{
redirect to cart;
addItemToCart(283746 , 1, 1, "Months", "1294");
}, 500);
}
I'm trying to make it so that instead of using a setTimeout it waits until the clearCart() has finished loading through ajax and then it runs the functions inside the setTimeout and I can't seem to figure this out.. I tried doing a callback but I'd say that it isn't correct..
function FirstFunction(callBack)
{
clearCart();
if (callback)
{
callback();
}
}
function SecondFunction()
{
buyButton();
}
FirstFunction(SecondFunction);
If you want to run some code when an Ajax response has arrived, put it in the done or success handler function. That is what those functions are for.
Don't guess how long the request is going to take.
Need to use done or success callback to avoid any random waiting time. like below:
function clearCart()
{
return jQuery.ajax({
});
}
function buyButton()
{
clearCart().done(function () {
addItemToCart(283746 , 1, 1, "Months", "1294");
});
}

Categories