I need help to get a value of a json for a function and pass this value of the function to the console, but now i'm recive var = undefined, follow the code below, thanks
var Site = {
baseUrl: "https://www.usereserva.com/",
visitUrl: "https://cloud-commerce-visit.oracleoutsourcing.com/"
}
var prodAPI = Site.baseUrl + "ccstoreui/v1/products/" + prodId;
var prodId = '0058597';
console.log("============= SCRIPT CALLCAPRODUCT ==============");
console.log("url API: " + prodAPI);
console.log("Id buscada: " + prodId);
var request = require('request');
var price;
function prodPrice() {
request(Site.baseUrl + "ccstoreui/v1/prices/" + prodId, function (error, response, body) {
var corpo = JSON.parse(body);
price = corpo['sale'];
console.log(price); // result 169
});
}
console.log("preço: " + prodPrice());
console.log("Requisição CALLPRODUCT foi bem sucedida");
console.log("================================================");
Yes, you are using prodId variable before assigning the value to prodId. This will return error. Here hoisting will take place. Your code will be compiled as
var Site = {
baseUrl: "https://www.usereserva.com/",
visitUrl: "https://cloud-commerce-visit.oracleoutsourcing.com/"
}
var prodId ;
var prodAPI = Site.baseUrl + "ccstoreui/v1/products/" + prodId; // so here
// prodId is undefined,thats why error.
prodId = '0058597';
console.log("============= SCRIPT CALLCAPRODUCT ==============");
console.log("url API: " + prodAPI);
console.log("Id buscada: " + prodId);
var request = require('request');
var price;
function prodPrice() {
request(Site.baseUrl + "ccstoreui/v1/prices/" + prodId, function (error, response, body) {
var corpo = JSON.parse(body);
price = corpo['sale'];
console.log(price); // result 169
});
}
console.log("preço: " + prodPrice());
console.log("Requisição CALLPRODUCT foi bem sucedida");
console.log("================================================");
initialize and assign the prodId variable first and then use it
var prodId = "0058597";
var prodAPI = Site.baseUrl + "ccstoreui/v1/products/" + prodId;
Another one is that you are not returning any value from prodPrice() method and default return is undefined.
return the required value from method.
Please read about hoisting in java script. this will help Hoisting
Use Let or const instead of var to avoid such problems.
https://medium.com/javascript-scene/javascript-es6-var-let-or-const-ba58b8dcde75
Related
Passing variables within the functions : I want to pass mentioned variable (insTypeDB) to another function. Please see the image.
//Getting Symbol details from DB API
var insTypeDB;
pm.sendRequest("http://192.168.14.116:8080/ords/unidata/symbol/symbol/" + dataArr[1], function (err, response) {
var resBoday = response.json()
insTypeDB = resBoday.items[0].instrument_type_id;
//var intInsTypeDB = parseInt(insTypeDB);
console.log("insTypeDB " + insTypeDB);
//pm.expect(insTypeDB).is.to.equals(2);
});
//Verify Instrument Type with DB API
pm.test("Row : " + i + " - " + dataArr[1] + " : Verify symbol Instrument type with DB", function () {
let insTypeRes = dataArr[2];
let intInsType = parseInt(insTypeRes);
console.log("insType " + intInsType);
pm.expect(insTypeDB).is.to.equals(intInsType);
});[enter image description here][1]
Passing Variables error
//Getting Symbol details from DB API
var insTypeDB;
pm.sendRequest("http://192.168.14.116:8080/ords/unidata/symbol/symbol/" + dataArr[1], function (err, response) {
var resBoday = response.json()
insTypeDB = resBoday.items[0].instrument_type_id;
//var intInsTypeDB = parseInt(insTypeDB);
console.log("insTypeDB " + insTypeDB);
//pm.expect(insTypeDB).is.to.equals(2);
//Verify Instrument Type with DB API
pm.test("Row : " + i + " - " + dataArr[1] + " : Verify symbol Instrument type with DB", function () {
let insTypeRes = dataArr[2];
let intInsType = parseInt(insTypeRes);
console.log("insType " + intInsType);
pm.expect(insTypeDB).is.to.equals(intInsType);
});[enter image description here][1]
});
add the test inside the sendRequest as it is a call back else use setTimeOut which will wait for the value to be populated
pm.sendRequest("http://192.168.14.116:8080/ords/unidata/symbol/symbol/" + dataArr[1], function (err, response) {
var resBoday = response.json()
insTypeDB = resBoday.items[0].instrument_type_id;
//var intInsTypeDB = parseInt(insTypeDB);
console.log("insTypeDB " + insTypeDB);
pm.varaible.set("insTypeDB",insTypeDB);
});
setTimeout(()=>{
pm.test("Row : " + i + " - " + dataArr[1] + " : Verify symbol Instrument type with DB", function () {
let insTypeRes = dataArr[2];
let intInsType = parseInt(insTypeRes);
console.log("insType " + intInsType);
pm.expect(pm.varaible.get("insTypeDB")).is.to.equals(intInsType);
})
},5000)
I am writing a function calling an API to fetch URLs. These are the steps that I wish to accomplish:
Parsing in an array of objects (restaurants) as arguments
For each object, call the Google Search API to get some imageURLs
Store those imageURLs in an array
Add imageURLs as an attribute called imageURLs to each object within the array in the argument
The code is able to log the imageURLs within the GET request, but outside of the request, imageURLs is just an empty array.
var googleSearch = function(restaurants, cb){
console.log("google starts");
const apiKey = google_apiKey;
const cseKey = cseID;
Array.from(restaurants).forEach(function(restaurant){
var keyWord = restaurant.name + " "+ restaurant.location.city
+ " "+ restaurant.location.state + " food";
var googleURL = "https://www.googleapis.com/customsearch/v1?key="+ apiKey +
"&q="+ keyWord +
"&searchType=image" +
"&cx=" + cseKey +
"&num=7" +
"&safe=medium"
;
//image URLs of each restaurants to be displayed in the front end
var imageURLs = [];
request
.get(googleURL,
{
json : true, headers: {
'User-Agent' : 'thaorell'
}
})
.then(function(response){
Array.from(response.items).forEach(function(item){
imageURLs.push(item.link)
});
})
.catch(e => {
console.log(e);
})
restaurant.imageURLs = imageURLs
})
cb(null, restaurants);
}
You're misunderstanding the Promise API:
var googleSearch = function (restaurants, cb) {
console.log("google starts");
const apiKey = google_apiKey;
const cseKey = cseID;
return Promise.all(Array.from(restaurants).map(function (restaurant) {
var keyWord = restaurant.name + " " + restaurant.location.city
+ " " + restaurant.location.state + " food";
var googleURL = "https://www.googleapis.com/customsearch/v1?key=" + apiKey +
"&q=" + keyWord +
"&searchType=image" +
"&cx=" + cseKey +
"&num=7" +
"&safe=medium"
;
return request
.get(googleURL,
{
json: true, headers: {
'User-Agent': 'thaorell'
}
}
)
.then(function (response) {
restaurant.imageURLs = Array.from(response.items).map(function (item) {
return item.link;
});
return restaurant;
})
})
)
.then(restaurants2 => cb(null, restaurants2))
.catch(cb)
}
As you can see you need to wait for all of the requests to finish before you pass the data back to the callback.
This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 6 years ago.
for(var i in companyTickerList) {
console.log('i = ' + i);
//construct url
var url = base_url + companyTickerList[i];
console.log('url = ' + url);
request(url, function(error, response, xml) {
if(!error && response.statusCode == 200) {
//load xml returned from GET to url
var cik_xml = cheerio.load(xml)
console.log('i = ' + i);
//map company ticker symbol to cik value scraped from xml
TickerToCIK[companyTickerList[i]] = cik_xml('company-info cik').text();
console.log('TICKER = ' + companyTickerList[i] + ' CIK = ' + cik_xml('company-info cik').text());
}
}
//CONSOLE LOG OUTPUT
i = 0
http://www.sec.gov/cgi-bin/browse..........SNPS
i = 1
http://www.sec.gov/cgi-bin/browse..........IBM
i = 2
http://www.sec.gov/cgi-bin/browse..........BA
i = 3
http://www.sec.gov/cgi-bin/browse..........GM
i = 4
http://www.sec.gov/cgi-bin/browse..........F
i = 5
http://www.sec.gov/cgi-bin/browse..........C
i = 6
http://www.sec.gov/cgi-bin/browse..........CVX
i = 6
TICKER = CVX CIK = 0000883241
i = 6
TICKER = CVX CIK = 0000037996
i = 6
TICKER = CVX CIK = 0000831001
i = 6
TICKER = CVX CIK = 0000093410
i = 6
TICKER = CVX CIK = 0001467858
i = 6
TICKER = CVX CIK = 0000012927
i = 6
TICKER = CVX CIK = 0000051143
Why is the iterator value i always equivalent to 6 in the callback function after each request call is triggered? It is making the keys for my TickerToCIK map always be CVX. Do I need to pass i as an argument to the callback function?
var is tricky :)
JavaScript actually evaluates your code like this:
var i;
for(i in companyTickerList) {
console.log('i = ' + i);
// ...
meaning, it's like var definition executed before your first line of code.
So, you actually have a variable i which gets updated 6 times and eventually i = 6.
Your request() callback is async, and by the time your first callback actually got invoked, the loop is long gone and i equals 6.
Solution:
One possible solution is to use an IIFE (Immediately-Invoked Function Expression).
That is:
(function (i) {
// async code using i
})(i);
Like so:
for (var i in companyTickerList) {
console.log('i = ' + i);
//construct url
var url = base_url + companyTickerList[i];
console.log('url = ' + url);
(function (i) {
request(url, function (error, response, xml) {
if (!error && response.statusCode == 200) {
//load xml returned from GET to url
var cik_xml = cheerio.load(xml);
console.log('i = ' + i);
//map company ticker symbol to cik value scraped from xml
TickerToCIK[companyTickerList[i]] = cik_xml('company-info cik').text();
console.log('TICKER = ' + companyTickerList[i] + ' CIK = ' + cik_xml('company-info cik').text());
}
});
})(i);
}
You will need to use a closure to implement this correctly. For example, something like this.
for(var i in companyTickerList) {
console.log('i = ' + i);
//construct url
var url = base_url + companyTickerList[i];
console.log('url = ' + url);
function(i){
request(url, functon(error, response, xml) {
if(!error && response.statusCode == 200) {
//load xml returned from GET to url
var cik_xml = cheerio.load(xml)
console.log('i = ' + i);
//map company ticker symbol to cik value scraped from xml
TickerToCIK[companyTickerList[i]] = cik_xml('company-info cik').text();
console.log('TICKER = ' + companyTickerList[i] + ' CIK = ' + cik_xml('company-info cik').text());
}
}
}(i)
}
I haven't tested the above, but you can see how I wrapped the request in a function, and passed that function the iterator value as an argument.
I have used node.js and request.js to access form information from our email services API. With the console.log in the function I am able to see all the info that I need. I have tried to access it outside of the function with dot notation(request.missionStatement) which I don't think is right. I want to be able to display this on a page within an express.js app.
var request = require('request');
// Basic Authentication credentials
var username = "user";
var password = "password";
var authenticationHeader = "Basic " + new Buffer(username + ":" + password).toString("base64");
// Search for Custom Data Objects Affiliate Falculty form
request(
{
url : "url to api",
headers : { "Authorization" : authenticationHeader }
},
function (error, response, body) {
var parsedData = JSON.parse(body);//convert text from API to JSON file
var missionStatement = [];
for (var i = 0; i < parsedData.elements.length ; i++) {
var individualStatement = "";
//Get text submission from form and push into array
individualStatement += (parsedData.elements[i].fieldValues[4].value + ", " + parsedData.elements[i].fieldValues[2].value + " " + parsedData.elements[i].fieldValues[3].value + ", " + parsedData.elements[i].fieldValues[0].value);
missionStatement.push(individualStatement);
};
console.log(missionStatement)
}
);
The variable missionStatement is a local variable declared inside an anonymous function passed as an argument to the request function, and thus it is inaccessible once the anonymous function returns. You must save your result elsewhere. Try something like this:
var request = require('request');
// Basic Authentication credentials
var username = "user";
var password = "password";
var authenticationHeader = "Basic " + new Buffer(username + ":" + password).toString("base64");
var result;
// Search for Custom Data Objects Affiliate Falculty form
request(
{
url : "url to api",
headers : { "Authorization" : authenticationHeader }
},
function (error, response, body) {
var parsedData = JSON.parse(body);//convert text from API to JSON file
var missionStatement = [];
for (var i = 0; i < parsedData.elements.length ; i++) {
var individualStatement = "";
//Get text submission from form and push into array
individualStatement += (parsedData.elements[i].fieldValues[4].value + ", " + parsedData.elements[i].fieldValues[2].value + " " + parsedData.elements[i].fieldValues[3].value + ", " + parsedData.elements[i].fieldValues[0].value);
missionStatement.push(individualStatement);
};
result = missionStatement;
displayResult();
});
function displayResult() {
console.log(result);
}
Your missionStatement will now be saved in result, but only after the anonymous callback to request() has been called (when the actual request is finished).
Using Sharepoint Online 2013 building an app using JSOM.
This current part is after the submission of data to a list (Which is working correctly) a modal will open allowing users to create a PDF off that List and other Lists. The current issue is that the data from the list must be ready on the client side before I can begin making it into a PDF, I have read over the literature on the "Promise" method and that is what I have been trying recently with little success.
function getQuoteDetails() {
var d = $.Deferred(function(){
var ListName = "Quote";
var context = new SP.ClientContext.get_current();
var lstObject = context.get_web().get_lists().getByTitle(ListName);
var camlQuery = new SP.CamlQuery();
//var _valuetofind = $('#QuoteID').text();
var _valuetofind = '1';
camlQuery.set_viewXml("<View><ViewFields>" +
"<FieldRef Name='Q_ID' />" +
"<FieldRef Name='CPY_ID' />" +
"<FieldRef Name='CUST_ID' />" +
"<FieldRef Name='Q_RaiseDate' />" +
"<FieldRef Name='Q_DueDate' />" +
"<FieldRef Name='Q_Price' />" +
"<FieldRef Name='Q_GST' />" +
"<FieldRef Name='Q_TotalPrice' />" +
"<FieldRef Name='Q_PurchaseOrder' />" +
"</ViewFields>" +
"<Query><Where><Contains>" +
"<FieldRef Name='Q_ID'/>" +
"<Value Type='Number'>" + _valuetofind + "</Value></Contains></Where></Query></View>");
var listItemCollection = lstObject.getItems(camlQuery);
context.load(listItemCollection, "Include(Q_ID, CPY_ID, CUST_ID, Q_RaiseDate, Q_DueDate, Q_Price, Q_GST, Q_TotalPrice, Q_PurchaseOrder)");
context.executeQueryAsync(onGetItemsSuccess, onGetItemsFail);
function onGetItemsSuccess(sender, args) {
var listItemEnumerator = listItemCollection.getEnumerator();
while (listItemEnumerator.moveNext()) {
var quotearray = [];
quotearray['Q_ID'] = listItemEnumerator.get_current().get_item('Q_ID');
quotearray['CPY_ID'] = listItemEnumerator.get_current().get_item('CPY_ID');
quotearray['CUST_ID'] = listItemEnumerator.get_current().get_item('CUST_ID');
quotearray['Q_RasiedDate'] = listItemEnumerator.get_current().get_item('Q_RasiedDate');
quotearray['Q_DueDate'] = listItemEnumerator.get_current().get_item('Q_DueDate');
quotearray['Q_Price'] = listItemEnumerator.get_current().get_item('Q_Price');
quotearray['Q_GST'] = listItemEnumerator.get_current().get_item('Q_GST');
quotearray['Q_TotalPrice'] = listItemEnumerator.get_current().get_item('Q_TotalPrice');
quotearray['Q_PurchaseOrder'] = listItemEnumerator.get_current().get_item('Q_PurchaseOrder');
}
d.resolve(quotearray);
}
function onGetItemsFail(sender, args) {
alert('Failed to get items. Error: ' + args.get_message());
}
});
return d.promise();
}
This code is then called by:
function CreateQuotePDF() {
getQuoteDetails().done(function (quotearray) {
var quotedetails = quotearray;
alert('Nothing'); <---- quotedetails is undefined at this point
});
alert('Nothing'); <---- quotedetails is undefined at this point
}
Hope you can help out!
Some recommendations
make sure you are using jQuery version >= 1.5 since Deferred object
was introduced in jQuery 1.5
there is no need to specify CAML ViewFields and value for the second parameter of SP.ClientContext.load function at the same time since both of them are used for specifying what properties to retrieve
always prefer to include failed callback for SP.ClientContext.executeQueryAsync function in order to handle any occurred error
Having said that i would suggest you the below more generic method for getting list items:
function getListItems(listTitle,propertiesToInclude)
{
var ctx = SP.ClientContext.get_current();
var web = ctx.get_web();
var list = web.get_lists().getByTitle(listTitle);
var items = list.getItems(SP.CamlQuery.createAllItemsQuery());
var includeExpr = 'Include(' + propertiesToInclude.join(',') + ')';
ctx.load(items,includeExpr);
var d = $.Deferred();
ctx.executeQueryAsync(function() {
var result = items.get_data().map(function(i){
return i.get_fieldValues();
});
d.resolve(result);
},
function(sender,args){
d.reject(args);
});
return d.promise();
}
In that case list items could be retrieved as shown below:
SP.SOD.executeFunc('SP.js', 'SP.ClientContext', function() {
var listTitle = 'Documents'; //set list title here
var properties = ['Title','ID']; //specify items properties here
getListItems(listTitle,properties)
.done(function(items){
console.log(items);
})
.fail(function(error){
console.log(error.get_message()); //if any error is occurred?
});
});