Error with setTimeout() function in for loop - javascript

I have the following script that I need to adjust so that each iteration has a one second pause before or after it executes the loop (it doesn't really matter which as long as the lag is there). I tried to add the setTimeout() function into the Try section of my code but it is still consistently failing. I also have tried to use "let" instead of "var" in the for loop but that failed as well. Any advice on how to add it in would be very appreciated. I'm having trouble finding an example of a similar setTimeout() function within a for loop online.
var ZB_DataExtension = 'C7_Unsubscribe_Response';
var ZB_DataExtension_Response = 'C7_Unsubscribe_Response';
var ZB_DataExtension_Logs = 'C7_CustUnsubscribe_Logs';
//Endpoint
var zeroBounceFullUrl = 'https://api.commerce7.com/v1//customer/CUST_ID';
//Extract results from Data Extension using DE key
var results = DataExtension.Init(ZB_DataExtension).Rows.Retrieve();
var updateDE_ZB = DataExtension.Init(ZB_DataExtension_Response);
var logsDE_ZB = DataExtension.Init(ZB_DataExtension_Logs);
var today = Format(Now(), "YYYY-MM-DD ");
for (var i = 0; i < results.length; i++ ) {
var item = results[i];
var zeroBounceUrlItem = "";
var ZB_Status = "";
var currentDateTime = Now();
try{
setTimeout(() => (
zeroBounceUrlItem = String(zeroBounceFullUrl).split("CUST_ID").join(String(item.C7_CustID));
var req = new Script.Util.HttpRequest(zeroBounceUrlItem);
req.emptyContentHandling = 0;
req.retries = 3;
req.continueOnError = true;
req.contentType = "application/json";
req.method = "PUT";
var payload='{"emailMarketingStatus": "Unsubscribed"}'
req.postData = payload ;
var resp = req.send();
var returnStatus= resp.returnStatus;
updateDE_ZB.Rows.Update({C7_API_Answer:String(returnStatus),ValidationDate:currentDateTime,ValidationUrl:String(zeroBounceUrlItem),EmailAddress:String(item.EmailAddress)}, ["C7_CustID"], [String(item.C7_CustID)]);
if (returnStatus==0) {
updateDE_ZB.Rows.Update({C7_API_Answer:String("Success"),ValidationDate:currentDateTime,ValidationUrl:String(zeroBounceUrlItem),EmailAddress:String(item.EmailAddress)}, ["C7_CustID"], [String(item.C7_CustID)]);
}
else {
//ZB_Status = String("ERRO ZB API Call");
//var responseJson = Platform.Function.ParseJSON(String(resp.content));
updateDE_ZB.Rows.Update({C7_API_Answer:String("Failure"),ValidationDate:currentDateTime,ValidationUrl:String(zeroBounceUrlItem),EmailAddress:String(item.EmailAddress)}, ["C7_CustID"], [String(item.C7_CustID)]);
}
var randomID = Platform.Function.GUID();
logsDE_ZB.Rows.Add({log_guid:String(randomID),C7_CustID:String(item.C7_CustID),Status:String("Success"),ValidationDate:currentDateTime,ValidationUrl:String(zeroBounceUrlItem)});
), 1000*i}
catch (err) {
var randomID = Platform.Function.GUID();
ZB_Status = String("ERRO AMPScript");
logsDE_ZB.Rows.Add({log_guid:String(randomID),C7_CustID:String(item.C7_CustID),Status:String("Failure"),ValidationDate:currentDateTime,ValidationUrl:String(zeroBounceUrlItem)});
}
}
</script>

Your loop will execute the right number of times and at the right interval, but the value of the variable item inside the timeout might not be what you expect.
Try this:
for (var i = 0; i < results.length; i++ ) {
(function(i){
setTimeout(function(){
var item = results[i];
var zeroBounceUrlItem = "";
var ZB_Status = "";
var currentDateTime = Now();
try{
zeroBounceUrlItem = String(zeroBounceFullUrl).split("CUST_ID").join(String(item.C7_CustID));
var req = new Script.Util.HttpRequest(zeroBounceUrlItem);
req.emptyContentHandling = 0;
req.retries = 3;
req.continueOnError = true;
req.contentType = "application/json";
req.method = "PUT";
var payload='{"emailMarketingStatus": "Unsubscribed"}'
req.postData = payload ;
var resp = req.send();
var returnStatus= resp.returnStatus;
updateDE_ZB.Rows.Update({C7_API_Answer:String(returnStatus),ValidationDate:currentDateTime,ValidationUrl:String(zeroBounceUrlItem),EmailAddress:String(item.EmailAddress)}, ["C7_CustID"], [String(item.C7_CustID)]);
if (returnStatus==0) {
updateDE_ZB.Rows.Update({C7_API_Answer:String("Success"),ValidationDate:currentDateTime,ValidationUrl:String(zeroBounceUrlItem),EmailAddress:String(item.EmailAddress)}, ["C7_CustID"], [String(item.C7_CustID)]);
}
else {
//ZB_Status = String("ERRO ZB API Call");
//var responseJson = Platform.Function.ParseJSON(String(resp.content));
updateDE_ZB.Rows.Update({C7_API_Answer:String("Failure"),ValidationDate:currentDateTime,ValidationUrl:String(zeroBounceUrlItem),EmailAddress:String(item.EmailAddress)}, ["C7_CustID"], [String(item.C7_CustID)]);
}
var randomID = Platform.Function.GUID();
logsDE_ZB.Rows.Add({log_guid:String(randomID),C7_CustID:String(item.C7_CustID),Status:String("Success"),ValidationDate:currentDateTime,ValidationUrl:String(zeroBounceUrlItem)});
catch (err) {
var randomID = Platform.Function.GUID();
ZB_Status = String("ERRO AMPScript");
logsDE_ZB.Rows.Add({log_guid:String(randomID),C7_CustID:String(item.C7_CustID),Status:String("Failure"),ValidationDate:currentDateTime,ValidationUrl:String(zeroBounceUrlItem)});
}
}, i*1000);
})(i);
}

Related

Getting text or json from server with native javascript can't work correctly

I need to get regions and cities from batuta.medunes.net. Program work correctly for regions but for cities can't work correctly even though I use same function and response from server is same like in first case with regions.
Here is code with functions that I use on onchange event at select tag in html:
var regions;
var get="";
function addRegion() {
var e = document.getElementById("countries");
console.log(e.selectedIndex);
console.log(countries[e.selectedIndex].alpha2Code);
var url="http://battuta.medunes.net/api/region/"+countries[e.selectedIndex].alpha2Code+"/all/?key=4b64da74d07ae8718ec91742d9a73b0a&callback=cb"
get="reg"
JsonpHttpRequest(url, "cb")
}
function addCity() {
var countr = document.getElementById("countries");
var regs = document.getElementById("regions");
var regStr=regions[regs.selectedIndex].region;
regStr = regStr.replace(/\s/g, '%20');
console.log(regStr);
var url="http://battuta.medunes.net/api/city/"+countries[countr.selectedIndex].alpha2Code+"/search/?region="+regStr+"&key=4b64da74d07ae8718ec91742d9a73b0a"
console.log(url);
get="city";
JsonpHttpRequest(url, "cb");
}
function JsonpHttpRequest(url, callback) {
var e = document.createElement('script');
e.src = url;
document.body.appendChild(e);
window[callback] = (data) => {
if(get=="reg"){
regions=data;
console.log(data);
select = document.getElementById('regions');
removeOptions(select);
for (var i = 0; i<Object.keys(data).length; i++){
var opt = document.createElement('option');
console.log(data[i].region);
opt.innerHTML = data[i].region;
select.appendChild(opt);
}
}
else{
console.log(data);
select = document.getElementById('cities');
removeOptions(select);
for (var i = 0; i<Object.keys(data).length; i++){
var opt = document.createElement('option');
console.log(data[i].city);
opt.innerHTML = data[i].city;
select.appendChild(opt);
}
}
}
}
function removeOptions(selectElement) {
var i, L = selectElement.options.length - 1;
for(i = L; i >= 0; i--) {
selectElement.remove(i);
}
}
I used console.log() and when I change region problem is stoping execution function JsonpHttpRequest(url, callback) at line before ...window[callback] = (data) => {...
so I can't manipulate with response from server.
Here is Console from browser:

Load Array with Excel Data and Return it

Can anyone assist me with loading an array with excel data and returning it as a function? This is my initial code:
var excel = require('exceljs');
var wb = new excel.Workbook();
var path = require('path');
var filePath = path.resolve(__dirname,'data.xlsx');
function signIn(){
var SignIn = [];
wb.xlsx.readFile(filePath).then(function(){
var sh = wb.getWorksheet("Sheet1");
for(var i = 1; i < 3; i++){
SignIn.push(sh.getRow(i).getCell(2).value);
}
});
return SignIn
}
Workbook.readFile is aynchronous, you need to use either a callback or promise type approach. Using promises we can try:
var excel = require('exceljs');
var wb = new excel.Workbook();
var path = require('path');
var filePath = path.resolve(__dirname,'data.xlsx');
function signIn() {
var SignIn = [];
return wb.xlsx.readFile(filePath).then( () => {
var sh = wb.getWorksheet("Sheet1");
for(var i = 1; i < 3; i++){
SignIn.push(sh.getRow(i).getCell(2).value);
}
return SignIn;
});
}
async function testReadData() {
try {
let data = await signIn();
console.log('testReadData: Loaded data: ', data);
} catch (error) {
console.error('testReadData: Error occurred: ', error);
}
}
testReadData();
Or you can use a callback type approach:
function signInWithCallback(callback) {
var SignIn = [];
wb.xlsx.readFile(filePath).then(function(){
var sh = wb.getWorksheet("Sheet1");
for(var i = 1; i < 3; i++){
SignIn.push(sh.getRow(i).getCell(2).value);
}
callback(SignIn);
});
}
signInWithCallback((data) => console.log('Callback: Data: ', data));

How can I convert CSV data to JSON data?

I wrote the code that gets data from a device.
The form of the data is csv. Below is the data value.
1,1.635946,1.636609,1.640240,1.636091
2,1.642825,1.640267,1.639013,1.636568
3,1.636835,1.636022,1.637664,1.637144
4,1.641332,1.641166,1.637950,1.640760
5,1.636041,1.637437,1.640702,1.633678
But I want the data in json format. So I tried using an online converter and got the following values:
[
{
"1": 2,
"1.635946": 1.642825,
"1.636609": 1.640267,
"1.640240": 1.639013,
"1.636091": 1.636568
},
{
"1": 3,
"1.635946": 1.636835,
"1.636609": 1.636022,
"1.640240": 1.637664,
"1.636091": 1.637144
}
]
What parts of my code should I modify if I want to get these values?
Below is my code.
var Timer;
var i = 0 ;
setTimeout(function(){
Timer = setInterval(function(){
port.write(meascommand+'\n');
i++;
if(i==5){
clearInterval(Timer);
}
},5000);
},1000);
port.on('data',function(devicevalue){
arrayvalue = devicevalue.toString();
eachvalue = arrayvalue.split(';');
var results = [];
var index = i ;
var ch0value = eachvalue[0] ;
var ch1value = eachvalue[1] ;
var ch2value = eachvalue[2] ;
var ch3value = eachvalue[3] ;
results[0] = index ;
results[1] = ch0value ;
results[2] = ch1value ;
results[3] = ch2value ;
results[4] = ch3value ;
console.log(results);
fs.appendFile(file,results+'\r\n',function(err){
if(err)
console.log(err);
});
});
};
function processFiles(files) {
var file = files[0];
var reader = new FileReader();
reader.onload = function (e) {
var output = document.getElementById("fileOutput");
var texto = e.target.result;
csvJSON(texto);
};
reader.readAsText(file);
}
function csvJSON(csv) {
var lines = csv.split("\n");
var result = [];
var headers;
for (var i = 0; i < lines.length; i++) {
headers = lines[i].split("\n");
}
var cont = 0;
for (var i = 0; i < lines.length; i++) {
var obj = {};
var currentline = lines[i].split("\n");
for (var j = 0; j < headers.length; j++) {
obj[cont] = currentline[j];
}
cont++;
result.push(obj);
}
return JSON.stringify(result); //JSON
}
Try to use below code. Credits go to: https://gist.github.com/iwek/7154578
NOTE: split(","). If lines contains , snippet won't work. But thats not the case in your data, as far as I can see.
function csvJSON(csv){
var lines=csv.split("\n");
var result = [];
var headers=lines[0].split(",");
for(var i=1;i<lines.length;i++){
var obj = {};
var currentline=lines[i].split(",");
for(var j=0;j<headers.length;j++){
obj[headers[j]] = currentline[j];
}
result.push(obj);
}
//return result; //JavaScript object
return JSON.stringify(result); //JSON
}

Wait Callback and our result data to take another proccess out of this function

i have this class (product).
var Product = function () {
this.products = [];
this.priceFrom = null;
this.priceTo = null;
this.countDone = 0;
};
Product.prototype = {
constructor: Product,
getProductsByPriceRange: function (priceFrom, priceTo) {
var xhrUrl = "<?= base_url('market/products/xhr_product_price_range') ?>";
var xhrData = {price_from: priceFrom, price_to: priceTo};
var xhrType = "json";
var UtilsClass = new Utils();
UtilsClass.xhrConnection(xhrUrl, xhrData, xhrType, function (data) {
/* MY DATA IS HERE */
});
},
buildList:function (products) {
for (var i = 0; i < products.length; i++) {
var product = products[i];
console.log("product");
}
},
buildOne: function (product) {
}
};
/*....more classes */
And another piece of code (out of product class):
var fromPrice = data.from;
var toPrice = data.to;
var ProductClass = new Product();
var lastCountDone = ProductClass.countDone;
ProductClass.priceFrom = fromPrice;
ProductClass.priceTo = toPrice;
var myProducts = ProductClass.getProductsByPriceRange(ProductClass.priceFrom, ProductClass.priceTo);
My question is... can i wait callback of UtilsClass.xhrConnection (in first piece) and use generated data of callback in second piece of code (out of first piece).
Any ideas would be very valuable to me. Thank you!
var Product = function () {
this.products = [];
this.priceFrom = null;
this.priceTo = null;
this.countDone = 0;
};
Product.prototype = {
constructor: Product,
getProductsByPriceRange: function (priceFrom, priceTo) {
var xhrUrl = "<?= base_url('market/products/xhr_product_price_range') ?>";
var xhrData = {price_from: priceFrom, price_to: priceTo};
var xhrType = "json";
var UtilsClass = new Utils();
return new Promise(function(resolve, reject){
UtilsClass.xhrConnection(xhrUrl, xhrData, xhrType, function (data) {
/* MY DATA IS HERE */
resolve(data)
});
});
},
buildList:function (products) {
for (var i = 0; i < products.length; i++) {
var product = products[i];
console.log("product");
}
},
buildOne: function (product) {
}
};
While calling,
var fromPrice = data.from;
var toPrice = data.to;
var ProductClass = new Product();
var lastCountDone = ProductClass.countDone;
ProductClass.priceFrom = fromPrice;
ProductClass.priceTo = toPrice;
var myProducts = ProductClass.getProductsByPriceRange(ProductClass.priceFrom, ProductClass.priceTo).then(function(data){%your data will be available here%});

Asynchronous execution of javascript code

I am studying javascript and json but I've some problems: I have a script that works with json but the performances of what I wrote aren't that good. The code works only if I do a debug step by step with firebug or other tools and that makes me think that the execution of the code (or a part of it ... the one that creates the table as you'll see) requires too much time so the browser stops it.
The code is:
var arrayCarte = [];
var arrayEntita = [];
var arraycardbyuser = [];
function displayArrayCards() {
var richiestaEntity = new XMLHttpRequest();
richiestaEntity.onreadystatechange = function() {
if(richiestaEntity.readyState == 4) {
var objectentityjson = {};
objectentityjson = JSON.parse(richiestaEntity.responseText);
arrayEntita = objectentityjson.cards;
}
}
richiestaEntity.open("GET", "danielericerca.json", true);
richiestaEntity.send(null);
for(i = 0; i < arrayEntita.length; i++) {
var vanityurla = arrayEntita[i].vanity_urls[0] + ".json";
var urlrichiesta = "http://m.airpim.com/public/vurl/";
var richiestaCards = new XMLHttpRequest();
richiestaCards.onreadystatechange = function() {
if(richiestaCards.readyState == 4) {
var objectcardjson = {};
objectcardjson = JSON.parse(richiestaCards.responseText);
for(j = 0; j < objectcardjson.cards.length; j++)
arrayCarte[j] = objectcardjson.cards[j].__guid__; //vettore che contiene i guid delle card
arraycardbyuser[i] = arrayCarte;
arrayCarte = [];
}
}
richiestaCards.open("GET", vanityurla, true);
richiestaCards.send(null);
}
var wrapper = document.getElementById('contenitoro');
wrapper.innerHTML = "";
var userTable = document.createElement('table');
for(u = 0; u < arrayEntita.length; u++) {
var userTr = document.createElement('tr');
var userTdcard = document.createElement('td');
var userTdinfo = document.createElement('td');
var br = document.createElement('br');
for(c = 0; c < arraycardbyuser[u].length; c++) {
var cardImg = document.createElement('img');
cardImg.src = "http://www.airpim.com/png/public/card/" + arraycardbyuser[u][c] + "?width=292";
cardImg.id = "immaginecard";
userTdcard.appendChild(br);
userTdcard.appendChild(cardImg);
}
var userdivNome = document.createElement('div');
userdivNome.id = "diverso";
userTdinfo.appendChild(userdivNome);
var userdivVanity = document.createElement('div');
userdivVanity.id = "diverso";
userTdinfo.appendChild(userdivVanity);
var nome = "Nome: ";
var vanityurl = "Vanity Url: ";
userdivNome.innerHTML = nome + arrayEntita[u].__title__;
userdivVanity.innerHTML = vanityurl + arrayEntita[u].vanity_urls[0];
userTr.appendChild(userTdcard);
userTr.appendChild(userTdinfo);
userTable.appendChild(userTr);
}
wrapper.appendChild(userTable);
}
The problem is that the code that should make the table doesn't wait for the complete execution of the code that works with the json files. How can I fix it? I would prefer,if possible, to solve that problem with something easy, without jquery and callbacks (I am a beginner).
You'll have to move som code around to make that work. at first, split it up in some functions, then it is easier to work with. I dont know if it works, but the idea is that first it loads the arrayEntita. When that is done, it fills the other 2 arrays. And when the last array has been filled, it builds the table.
var arrayCarte = [];
var arrayEntita = [];
var arraycardbyuser = [];
function displayArrayCards() {
var richiestaEntity = new XMLHttpRequest();
richiestaEntity.onreadystatechange = function () {
if (richiestaEntity.readyState == 4) {
var objectentityjson = {};
objectentityjson = JSON.parse(richiestaEntity.responseText);
arrayEntita = objectentityjson.cards;
BuildArrayEntita();
}
}
richiestaEntity.open("GET", "danielericerca.json", true);
richiestaEntity.send(null);
}
function BuildArrayEntita() {
for (i = 0; i < arrayEntita.length; i++) {
var vanityurla = arrayEntita[i].vanity_urls[0] + ".json";
var urlrichiesta = "http://m.airpim.com/public/vurl/";
var richiestaCards = new XMLHttpRequest();
richiestaCards.onreadystatechange = function () {
if (richiestaCards.readyState == 4) {
var objectcardjson = {};
objectcardjson = JSON.parse(richiestaCards.responseText);
for (j = 0; j < objectcardjson.cards.length; j++)
arrayCarte[j] = objectcardjson.cards[j].__guid__; //vettore che contiene i guid delle card
arraycardbyuser[i] = arrayCarte;
arrayCarte = [];
//If it is the last call to populate arraycardbyuser, build the table:
if (i + 1 == arrayEntita.length)
BuildTable();
}
}
richiestaCards.open("GET", vanityurla, true);
richiestaCards.send(null);
}
}
function BuildTable() {
var wrapper = document.getElementById('contenitoro');
wrapper.innerHTML = "";
var userTable = document.createElement('table');
for (u = 0; u < arrayEntita.length; u++) {
var userTr = document.createElement('tr');
var userTdcard = document.createElement('td');
var userTdinfo = document.createElement('td');
var br = document.createElement('br');
for (c = 0; c < arraycardbyuser[u].length; c++) {
var cardImg = document.createElement('img');
cardImg.src = "http://www.airpim.com/png/public/card/" + arraycardbyuser[u][c] + "?width=292";
cardImg.id = "immaginecard";
userTdcard.appendChild(br);
userTdcard.appendChild(cardImg);
}
var userdivNome = document.createElement('div');
userdivNome.id = "diverso";
userTdinfo.appendChild(userdivNome);
var userdivVanity = document.createElement('div');
userdivVanity.id = "diverso";
userTdinfo.appendChild(userdivVanity);
var nome = "Nome: ";
var vanityurl = "Vanity Url: ";
userdivNome.innerHTML = nome + arrayEntita[u].__title__;
userdivVanity.innerHTML = vanityurl + arrayEntita[u].vanity_urls[0];
userTr.appendChild(userTdcard);
userTr.appendChild(userTdinfo);
userTable.appendChild(userTr);
}
wrapper.appendChild(userTable);
}
i dont know if this check:
if (i + 1 == arrayEntita.length)
BuildTable();
but else you have to check if alle responseses have returned before executing buildtable();
AJAX requests are asynchronous. They arrive at an unknown period during execution and JavaScript does not wait for the server to reply before proceeding. There is synchronous XHR but it's not for ideal use. You'd lose the whole idea of AJAX if you do so.
What is usually done is to pass in a "callback" - a function that is executed sometime later, depending on when you want it executed. In your case, you want the table to be generated after you receive the data:
function getData(callback){
//AJAX setup
var richiestaEntity = new XMLHttpRequest();
//listen for readystatechange
richiestaEntity.onreadystatechange = function() {
//listen for state 4 and ok status (200)
if (richiestaEntity.readyState === 4 && richiestaEntity.status === 200) {
//execute callback when data is received passing it
//what "this" is in the callback function, as well as
//the returned data
callback.call(this,richiestaEntity.responseText);
}
}
richiestaEntity.open("GET", "danielericerca.json"); //third parameter defaults to true
richiestaEntity.send();
}
function displayArrayCards() {
//this function passed to getData will be executed
//when data arrives
getData(function(returnedData){
//put here what you want to execute when getData receives the data
//"returnedData" variable inside this function is the JSON returned
});
}
As soon as you have made the ajax call, put all of the rest of the code inside the readystatechange function. This way, it will execute everything in order.
Edit: #Dappergoat has explained it better than I can.

Categories

Resources