I am making a POST request with Axios within a for loop to create leads in mass. The leads get created but the issue that I'm noticing is that even though I get a 200 response, in the network tab under timing, the requests are actually never finished, they just say "stalled".
Below is a screenshot of what I'm talking about
This can become a problem, because if I do other POST requests like this, not all the requests will go through. I think I read somewhere that Google Chrome only allows up to 6 connections open or something like that. If these requests are stalling, I can only assume that those connections are staying open, and that's what's causing this to happen.
So I guess my question is, what's the best way to put this POST request in a for loop without the requests stalling? Should I make it asynchronous, and if so how would I do that with my code?
Here is my server.js
app.get('/create*', (request, response) => {
var baseurl = 'https://OURACC.nocrm.io/api/v2/'
var apikey = 'APIKEY'
var title = "";
var description = "";
var tags = [];
var pathname = request.url; // retrieves the requested pathname (ie, /crm/path)
pathname = pathname.split('?');
pathname = pathname[0].split('/')
var parameters = request.query.params;
var path = pathname[2]; // gets request path for the crm
title = parameters.title
description = parameters.description
tags = parameters.tags
var params = {
title: title,
description: description,
tags: tags
}
if(path === 'leads'){
// console.log("Inside Lead Creation");
axios.post(baseurl + path,
params
,{
headers: {'X-API-KEY': apikey, content_type: "json", accept: "application/json"}
}).then(function(res){
console.log("Lead Created");
}).catch(function(error){
console.log("Error: " + error);
})
}
})
This is where I call it client side
CreateLeads(){
var prospects = this.state.Prospects;
var description = "";
var title = "";
var tags = [];
for(var i = 0; i < prospects.length; i++){
tags = prospects[i].tags;
title = prospects[i].leadName;
description = "Business Name: " + prospects[i].businessName + "\n" +
"Customer Number: " + prospects[i].custNumber + "\n" +
"Corporate Name: " + prospects[i].corpName + "\n" +
"Corporate Contact Name: " + prospects[i].corpContName + "\n" +
"Corporate Phone: " + prospects[i].corpPhone + "\n" +
"Corporate Email: " + prospects[i].corpEmail + "\n" +
"Customer First Name: " + prospects[i].custFirst + "\n" +
"Customer Last Name: " + prospects[i].custLast + "\n" +
"Street: " + prospects[i].street + "\n" +
"City: " + prospects[i].city + "\n" +
"State: " + prospects[i].state + "\n" +
"Zip: " + prospects[i].zip + "\n" +
"Phone 1: " + prospects[i].phone + "\n" +
"Category: " + prospects[i].category;
var data = {
title: title,
description: description,
tags: tags,
}
console.log(data);
$.get('/create/leads', {params: data}).then(response => {
console.log(response);
}).catch(error => {
console.log("Error: " + error);
})
}
}
Related
I use this code to show a response of an API request and wanted to seperate my two res.write() parts.
I tried a paragraph but VS is crying :)
app.post("/", function(req, res) {
var crypto = req.body.crypto;
var fiat = req.body.fiat;
var baseUrl = "https://apiv2.bitcoinaverage.com/indices/global/ticker/";
var url = baseUrl + crypto + fiat;
request(url, function(error, response, body) {
var data = JSON.parse(body);
var price = data.last;
var currentDate = data.display_timestamp;
res.write("<p>date: " + currentDate</p>);
res.write(
"Result: Price of " + crypto + " in " + fiat + " is " + price + "."
);
res.send();
});
});
I think you have a typo in this line:
res.write("<p>date: " + currentDate</p>);
It should be:
res.write("<p>date: " + currentDate + "</p>");
In the first version, it is having the closing tag as plain javascript, which is wrong. Should be inside a string (as you do with the opening tag).
I made a block in which the request to the specified URL occurs.
Inside this block, I can work with the data from response, but outside this block I can not get this data because of asynchrony.
Is it possible to simulate a synchronous request in blockly or in some other way, save the received data to a global variable?
code of the created block:
Blockly.Blocks['request'] =
'<block type="request">'
+ ' <value name="URL">'
+ ' <shadow type="text">'
+ ' <field name="TEXT">text</field>'
+ ' </shadow>'
+ ' </value>'
+ ' <value name="LOG">'
+ ' </value>'
+ ' <value name="WITH_STATEMENT">'
+ ' </value>'
+ ' <mutation with_statement="false"></mutation>'
+ '</block>';
Blockly.Blocks['request'] = {
init: function() {
this.appendDummyInput('TEXT')
.appendField('request');
this.appendValueInput('URL')
.appendField('URL');
this.appendDummyInput('WITH_STATEMENT')
.appendField('with results')
.appendField(new Blockly.FieldCheckbox('FALSE', function (option) {
var delayInput = (option == true);
this.sourceBlock_.updateShape_(delayInput);
}), 'WITH_STATEMENT');
this.appendDummyInput('LOG')
.appendField('log level')
.appendField(new Blockly.FieldDropdown([
['none', ''],
['info', 'log'],
['debug', 'debug'],
['warning', 'warn'],
['error', 'error']
]), 'LOG');
this.setInputsInline(false);
this.setPreviousStatement(true, null);
this.setNextStatement(true, null);
this.setColour(230);
this.setTooltip('Request URL');
this.setHelpUrl('https://github.com/request/request');
},
mutationToDom: function() {
var container = document.createElement('mutation');
container.setAttribute('with_statement', this.getFieldValue('WITH_STATEMENT') === 'TRUE');
return container;
},
domToMutation: function(xmlElement) {
this.updateShape_(xmlElement.getAttribute('with_statement') == 'true');
},
updateShape_: function(withStatement) {
// Add or remove a statement Input.
var inputExists = this.getInput('STATEMENT');
if (withStatement) {
if (!inputExists) {
this.appendStatementInput('STATEMENT');
}
} else if (inputExists) {
this.removeInput('STATEMENT');
}
}};
Blockly.JavaScript['request'] = function(block) {
var logLevel = block.getFieldValue('LOG');
var URL = Blockly.JavaScript.valueToCode(block, 'URL', Blockly.JavaScript.ORDER_ATOMIC);
var withStatement = block.getFieldValue('WITH_STATEMENT');
var logText;
if (logLevel) {
logText = 'console.' + logLevel + '("request: " + ' + URL + ');\n'
} else {
logText = '';
}
if (withStatement === 'TRUE') {
var statement = Blockly.JavaScript.statementToCode(block, 'STATEMENT');
if (statement) {
var xmlhttp = "var xmlHttp = new XMLHttpRequest();";
var xmlopen = "xmlHttp.open('POST', " + URL + ", true);";
var xmlheaders = "xmlHttp.setRequestHeader('Content-type', 'application/json');\n" +
"xmlHttp.setRequestHeader('Authorization', 'Bearer psokmCxKjfhk7qHLeYd1');";
var xmlonload = "xmlHttp.onload = function() {\n" +
" console.log('recieved:' + this.response);\n" +
" var response = this.response;\n" +
" var brightness = 'brightness: ' + JSON.parse(this.response).payload.devices[0].brightness;\n" +
" " + statement + "\n" +
"}";
var json = JSON.stringify({
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"inputs": [{
"intent": "action.devices.QUERY",
"payload": {
"devices": [{
"id": "0",
"customData": {
"smartHomeProviderId": "FkldJVJCmDNSaoLkoq0txiz8Byf2Hr"
}
}]
}
}]
});
var xmlsend = "xmlHttp.send('" + json + "');";
var code = xmlhttp + '\n' + xmlopen + '\n' + xmlheaders + '\n' + xmlonload + '\n' + xmlsend;
return code;
} else {
var xmlhttp = "var xmlHttp = new XMLHttpRequest();";
var xmlopen = "xmlHttp.open('POST', " + URL + ", true);";
var xmlheaders = "xmlHttp.setRequestHeader('Content-type', 'application/json');\n" +
"xmlHttp.setRequestHeader('Authorization', 'Bearer psokmCxKjfhk7qHLeYd1');";
var xmlonload = "xmlHttp.onload = function() {\n" +
" console.log('recieved:' + this.response);\n" +
"}";
var json = JSON.stringify({
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"inputs": [{
"intent": "action.devices.QUERY",
"payload": {
"devices": [{
"id": "0",
"customData": {
"smartHomeProviderId": "FkldJVJCmDNSaoLkoq0txiz8Byf2Hr"
}
}]
}
}]
});
var xmlsend = "xmlHttp.send('" + json + "');";
var code = xmlhttp + '\n' + xmlopen + '\n' + xmlheaders + '\n' + xmlonload + '\n' + xmlsend;
return code;
}
} else {
var xmlhttp = "var xmlHttp = new XMLHttpRequest();";
var xmlopen = "xmlHttp.open('POST', " + URL + ", true);";
var xmlheaders = "xmlHttp.setRequestHeader('Content-type', 'application/json');\n" +
"xmlHttp.setRequestHeader('Authorization', 'Bearer psokmCxKjfhk7qHLeYd1');";
var xmlonload = "xmlHttp.onload = function() {\n" +
" console.log('recieved:' + this.response);\n" +
"}";
var json = JSON.stringify({
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"inputs": [{
"intent": "action.devices.QUERY",
"payload": {
"devices": [{
"id": "0",
"customData": {
"smartHomeProviderId": "FkldJVJCmDNSaoLkoq0txiz8Byf2Hr"
}
}]
}
}]
});
var xmlsend = "xmlHttp.send('" + json + "');";
var code = xmlhttp + '\n' + xmlopen + '\n' + xmlheaders + '\n' + xmlonload + '\n' + xmlsend;
return code;
}};
We actually use Promises extensively in our Blockly environment. My suggestion would be to Promisify this and then use a generator function. For example, we use the co library to wrap our generated code, then use yield statements for asynchronous values to make them behave synchronously. For example:
For a block setup similar to this --
The generated code would be something like this (simplified) --
co(function* () {
var getUsername;
// getFieldValue makes an asynchronous call to our database
getUsername = (yield getFieldValue("username", "my user record Id", "users"));
Promise.all(inputPromises)
let inputPromises = [];
inputPromises.push('User name is');
inputPromises.push(getUsername);
yield new Promise(function(resolve, reject) {
Promise.all(inputPromises).then(function(inputResults) {
let [TITLE, MESSAGE] = inputResults;
let activity = "toastMessage";
let LEVEL = "success";
try {
var params = {message: MESSAGE, title: TITLE, level: LEVEL};
interface.notification(params);
return resolve();
} catch(err) {
return reject(err);
}
}).catch(reject);
});
return true;
}
As you may have noticed, though, this isn't always as easy as just sticking a "yield" before the block. Depending on your setup, you may have to get more creative using Promise.all to get values in your block, etc. (We actually wound up editing a bunch of the Blockly core blocks to append 'yield' in front of inputs which had a "promise" type set amongst their output types in order to make this work, but based on your setup, this may be overkill.)
Obviously, you would need to make sure this was either transpiled or run in an environment which supports ES6.
Of course, once you enter an asynchronous setup, there's not really any going back -- co functions themselves return a Promise, so you will need to deal with that appropriately. But in general, we've found this to be a pretty robust solution, and I'm happy to help you figure it out in more detail.
You can have blocks that execute asynchronously without Promises, async functions, or callbacks by using the JS Interpreter (docs, GitHub), conveniently written by the same guy that created Blockly. JS Interpreter is a JavaScript-in-JavaScript implementation. This does mean there needs to be a lot of code to connect the functions/commands of the main JS VM to the interpreter's embedded implementation.
Blockly has a few demonstrations of doing this (src). In particular, you'll want to investigate async-execution.html and the wait block implementation. You can find the wait block running live here.
Conveniently, the interpreter's doc's section on External API happens to use XMLHttpRequest as its example implementation. This should should be a good starting point for your request block's implementation.
is there a standard established way to do the following:
curl -i "http://api.waqi.info/feed/shanghai/?token=demo"
returns
{
status: "ok",
data: {
aqi: 70,
time: {
s: "2016-12-11 12:00:00"
},
city: {
name: "Shanghai",
url: "http://aqicn.org/city/shanghai/",
geo: [
"31.2047372",
"121.4489017"
]
},
iaqi: {
pm25: "..."
}
}
}
i want to make a simple page that calls the API and formats the result. but i want to do it in the browser so that i can host a serverless webpage.
Ive look at Angular and react but it seems an awful lot of setup and baggage to do something simple like this.
i could write the jscript and html from scratch but also feels like there should be some libraries to support this.
You can write an ajax call to get the data like this:
fetch('http://api.waqi.info/feed/shanghai/?token=demo')
.then(function(response) {
return response.json();
})
.then(function(jsonData) {
console.log(jsonData); //the data you want to get
});
More information here
If you want to use some library, you can try superagent
I have used jQuery plugin and used $.ajax() method: See here.
Later, I split all data using keys as shown below;
$.ajax({
url: 'http://api.waqi.info/feed/shanghai/?token=demo',
success: function(ajax) {
console.log(ajax);
let data = ajax.data; // Object
let api = data.api; // Int
let attributions = data.attributions; // Array [3]
let cityCoords = data.city.geo; // Array [2]
let cityName = data.city.name; // String
let cityUrl = data.city.url; // String
let dominentpol = data.dominentpol; // String
let iaqi = data.iaqi; // Object Keys = [co, d, h, no2, o3, p ,pm10, pm25, so2, t, w, wd]
let idx = data.idx; // Int
let time = data.time; // Object Keys = [s, tz, v]
let status = ajax.status;
console.log("Data Object: "
+ data +
"\nAPI Version: "
+ api +
"\nAttributions #1 Name: "
+ attributions[0].name +
"\nAttributions #1 Url: "
+ attributions[0].url +
"\nAttributions #2 Name: "
+ attributions[1].name +
"\nAttributions #2 Url: "
+ attributions[1].url +
"\nAttributions #3 Name: "
+ attributions[2].name +
"\nAttributions #3 Url: "
+ attributions[2].url +
"\nCity Longitude: "
+ cityCoords[0] +
"\nCity Latitude: "
+ cityCoords[1] +
"\nCity Name: "
+ cityName +
"\nCity Url: "
+ cityUrl +
"\dDominentpol: "
+ dominentpol +
"\nIaqi Key [co]: "
+ iaqi.co +
"\nIaqi Key [d]: "
+ iaqi.d +
"\nIaqi Key [h]: "
+ iaqi.h +
"\nIaqi Key [no2]: "
+ iaqi.no2 +
"\nIaqi Key [o3]: "
+ iaqi.o3 +
"\nIaqi Key [p]: "
+ iaqi.p +
"\nIaqi Key [pm10]: "
+ iaqi.pm10 +
"\nIaqi Key [pm25]: "
+ iaqi.pm25 +
"\nIaqi Key [so2]: "
+ iaqi.so2 +
"\nIaqi Key [t]: "
+ iaqi.t +
"\nIaqi Key [w]: "
+ iaqi.w +
"\nIaqi Key [wd]: "
+ iaqi.wd +
"\nIdx: "
+ idx +
"\nTime Key = [s]: "
+ time.s +
"\nTime Key = [tz]:"
+ time.tz +
"\nTime Key = [v]:"
+ time.v +
"\nStatus: "
+ status);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I have an array of items:
var myArr = ['item1', 'item2', 'item3'];
I'm attempting to loop over these items and check if they exist in my database. If the item does not exist, then I add it to the database.
var sql = 'Select * from DB where item="' + myArr[i] + '"';
connection.query(sql, function(e, r, f) {
if(!e && r.length <= 0) {
performInsertOnDB(myArr[i]);
}
});
My trouble is, the reference to variable i will not stay as connnection.query is asynchronous. I need to wait until the first select finishes before I can continue. I'm trying to use the Async library to accomplish this, but I must not be fully grasping how to perform the task.
This is what I have so far:
async.each(lootArray, function(lootItem, addLootItem) {
var sql = "SELECT * FROM loot_history WHERE date = DATE('" + moment(lootItem[1]).format('YYYY-MM-DD') + "') AND time = '" + lootItem[2] + "' AND itemId = " + lootItem[4];
connection.query(sql, function(error, results, fields) {
if (error) {
sendDiscordMessage(loachannel, error + ', <#105094681141977088>');
return false;
} else {
if (results.length > 0) {
//duplicates.push(lootArray[i]);
} else {
addLootItem(lootItem);
}
}
});
}, function(err) {
// if any of the file processing produced an error, err would equal that error
if (err) {
// One of the iterations produced an error.
// All processing will now stop.
console.log('A file failed to process');
} else {
console.log('All files have been processed successfully');
}
});
function addLootItem(lootItem) {
var sql = "INSERT INTO loot_history SET player = " + lootItem[0] + ", date = " + moment(lootItem[1]).format('YYYY-MM-DD') + ", time = '" + lootItem[2] + ", item = " + lootItem[3] + ", itemId = " + lootItem[4] + ", itemString=" + lootItem[5] + ", response= " + lootItem[6] + ", votes= " + lootItem[7] + ", class= " + lootItem[8] + ", instance=" + lootItem[9] + ", boss=" + lootItem[10] + ", gear1=" + lootItem[11] + ", gear2=" + lootItem[12] + ", reasponseId=" + lootItem[13] + ", isAwardReason=" + lootItem[14];
connection.query(sql, function(error, results, fields) {
if (error) {
sendDiscordMessage(loachannel, error + ', <#105094681141977088>');
}
});
}
EDIT: Everything works, except the callback AddLootItem is not firing. Why is this callback not getting called? I can set log events in that if statement that execute, but the function itself never fires.
The problem is that the name of async callback is the same as the function you want to be called when the item does not exist. Try to change the name in the function to something else let's say: callback, and call it in your if statement or pass it to addLootItem, and call it there once the item added.
async.each(lootArray, function(lootItem, callback) {
var sql = "SELECT * FROM loot_history WHERE date = DATE('" + moment(lootItem[1]).format('YYYY-MM-DD') + "') AND time = '" + lootItem[2] + "' AND itemId = " + lootItem[4];
connection.query(sql, function(error, results, fields) {
if (error) {
sendDiscordMessage(loachannel, error + ', <#105094681141977088>');
calback(err);
} else {
if (results.length > 0) {
//duplicates.push(lootArray[i]);
callback();
} else {
addLootItem(lootItem, callback);
}
}
});
}, function(err) {
// if any of the file processing produced an error, err would equal that error
if (err) {
// One of the iterations produced an error.
// All processing will now stop.
console.log('A file failed to process');
} else {
console.log('All files have been processed successfully');
}
});
function addLootItem(lootItem, done) {
var sql = "INSERT INTO loot_history SET player = " + lootItem[0] + ", date = " + moment(lootItem[1]).format('YYYY-MM-DD') + ", time = '" + lootItem[2] + ", item = " + lootItem[3] + ", itemId = " + lootItem[4] + ", itemString=" + lootItem[5] + ", response= " + lootItem[6] + ", votes= " + lootItem[7] + ", class= " + lootItem[8] + ", instance=" + lootItem[9] + ", boss=" + lootItem[10] + ", gear1=" + lootItem[11] + ", gear2=" + lootItem[12] + ", reasponseId=" + lootItem[13] + ", isAwardReason=" + lootItem[14];
connection.query(sql, function(error, results, fields) {
if (error) {
sendDiscordMessage(loachannel, error + ', <#105094681141977088>');
}
done();
});
}
I'm working on a web app that reads and writes files. This is in my index.js route file. When I load the results page, it says that it cannot load the coverage file. I understand that this is because it hasn't finished writing before the requests page loads. My question is how can I load the file and update the page when it is done loading?
router.get('/results?', function(req, res) {
var id = req.query.id;
var sequence = fs.readFileSync(temppath + id + ".sequence");
var refseq = fs.readFileSync(temppath + id + ".refseq");
var coverage = fs.readFileSync(temppath + id + ".coverage.txt");
res.render('results', { title: 'Results', sequence: sequence, refseq:refseq, coverage: coverage});
});
router.post('/calculate-coverage', function(req, res) {
var id = crypto.randomBytes(20).toString('hex');
var sequence = req.body.sequence;
var sequence = ">" + temppath + id + "\n" + sequence.replace(/ /g,'');
var refseq = req.body.refseq;
var refseq = ">" + temppath + id + "\n" + refseq.replace(/ /g,'');
//display progress here
//write to files
var sequenceFile = temppath + id + ".sequence";
var refseqFile = temppath + id + ".refseq";
fs.writeFileSync(sequenceFile, sequence);
fs.writeFileSync(refseqFile, refseq);
//bamtools coverage script
var cmd = 'bash ./scripts/coverage.sh ' + sequenceFile + " " + refseqFile + " " + temppath + id;
console.log(cmd);
exec(cmd, function(error, stdout, stderr) {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
});
res.location("results?id="+id);
res.redirect("results?id="+id);
});
Never use synchronous function like this. Because if you have 100 concurrent requests and within one of them sync function is used, other 99 clients will wait till this function ends. Instead use async analogs:
fs.readFile(temppath + id + ".sequence", "utf8", function(err, sequence) {
fs.readFile(temppath + id + ".refseq", "utf8", function(err, refseq) {
fs.readFile(temppath + id + ".coverage.txt", "utf8", function(err, coverage) {
res.render('results', { title: 'Results', sequence: sequence, refseq:refseq, coverage: coverage});
});
});
});