javascript embedded function and embedded variable scope - javascript

I am writing a small app that will use the jQuery ajax call to make SOAP calls to a third party API. I want to make the following function "generic" but am running into variable scoping issues in the innermost function in the "done()" ajax method. That function is where the good stuff is returned. I want the key, value pairs to be placed in the "result" object that is passed into the APICall function but i don't know how to reference it down there.
I don't think I can modify the function parameter list in the "done" section can I? I just tried adding the passed in "result" to the "done" functions and there were no syntax issues but it is not working.
Ideas?
function APICall(method, username, password, payload, result) {
var wsUrl = "https://localhost.my.company.org/API/Service.asmx";
var soapRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<soap:Envelope \n"
+ " soap:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" \n"
+ " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" \n"
+ " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\" \n"
+ " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" \n"
+ " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"> \n"
+ " <soap:Body> \n"
+ " <__METHOD__ xmlns=\"http://THIRD-PARTY.API.Web.Service/\"> \n"
+ " <UserName>__USERNAME__</UserName> \n"
+ " <Password>__PASSWORD__</Password> \n"
+ " __PAYLOAD__ \n" + " </__METHOD__> \n"
+ " </soap:Body> \n" + "</soap:Envelope>\n";
soapRequest = soapRequest.replace(/__METHOD__/g, method);
soapRequest = soapRequest.replace(/__USERNAME__/g, username);
soapRequest = soapRequest.replace(/__PASSWORD__/g, password);
soapRequest = soapRequest.replace(/__PAYLOAD__/g, payload);
$.ajax({
type : "POST",
headers : {
SOAPAction : '"http://THIRD-PARTY.API.Web.Service/' + method + '"'
},
url : wsUrl,
contentType : "text/xml",
dataType : "xml",
data : soapRequest,
error : processAJAXError
}).done(
function(data, textStatus, jqXHR) {
$($.parseXML($(data).find(method + 'Result').text())).find(
'Data').each(
function(key, val) {
result[$(val).find('Room').text()] = $(val).find(
'ID').text();
console.log($(val).find('Room').text() + ' => '
+ $(val).find('ID').text());
});
});
}

Try bind();
.done(
function(data, textStatus, jqXHR) {
.
.
.
}.bind(result));

Related

Sending XML in AJAX request always receives an error

I am sending XML to a particular web service. When I view the response in my browser's network tab, it seems it's a proper request as I expected, but still the error callback in my JS code is firing hence handling it as an error instead of making use of the returned response as expected. What could be the cause of this?
const endpoint = "https://secure1.sandbox.directpay.online/API/v6/";
$(document).ready(function() {
$("#sendBtn").click(function() {
var x2js = new X2JS();
var req = "<?xml version='1.0' encoding='utf-8'?>" +
"<API3G>" +
"<CompanyToken>TOKEN-TO-BE-PLACED-HERE</CompanyToken>" +
"<Request>createToken</Request>" +
"<Transaction>" +
"<PaymentAmount>450.00</PaymentAmount>" +
"<PaymentCurrency>USD</PaymentCurrency>" +
"<CompanyRef>49FKEOA</CompanyRef>" +
"<RedirectURL>https://secure1.sandbox.directpay.online/payv2.php?ID=TOKEN-HERE</RedirectURL>" +
"<BackURL>http://localhost/computicket_node_server/</BackURL>" +
"<CompanyRefUnique>0</CompanyRefUnique>" +
"<PTL>5</PTL>" +
"</Transaction>" +
"<Services>" +
"<Service>" +
"<ServiceType>5525</ServiceType>" +
"<ServiceDescription>Flight from Malawi to India</ServiceDescription>" +
"<ServiceDate>2013/12/20 19:00</ServiceDate>" +
"</Service>" +
"</Services>" +
"</API3G>";
$.ajax({
url: endpoint,
type: "POST",
data: req,
//timeout: 5000,
dataType: "text/xml",
success: function(response) {
var res = JSON.stringify(x2js.xml_str2json(response));
console.log(res);
document.getElementById("response").innerHTML = res;
},
error: function(xhr, status, error) {
console.log(xhr, status, error);
}
});
});
});
The results that I am getting
Is dataType not the responding type? You should use contentType
contentType: "application/xml",
Don't know what type you expect to get back, I think you can avoid it.

Can't send parameter containing "#" to dot net web service from ajax

Cant send parameter containing "#" to dot net web service from ajax.
var s = encodeURI(
"http://subdomain.mydomain.domain.asmx/getData?OUserId=" + UserId +
"&Token=" + Token +
"&OrgId=" + OrgId +
'&Message=' + Message +
'&Schoolid=' + SchoolId +
'&SessionId=" ' + SessionId +
'&UnicodeValue=' + UnicodeValue +
'&ClassID=' + ClassIdCommaSeparated.toString()
);
$.ajax({
url: s,
error: function(err) {
alert(err);
},
success: function(data) {....
}
});
Here classIdCommaSeparated is 1#1#1#1#1,1#1#1#1#1,1#1#1#1#1.
Use encodeURIComponent on the individual parts, rather than encodeURI on the whole:
var s = "http://subdomain.mydomain.domain.asmx/getData?OUserId=" + encodeURIComponent(UserId) +
"&Token=" + encodeURIComponent(Token) +
"&OrgId=" + encodeURIComponent(OrgId) +
'&Message=' + encodeURIComponent(Message) +
'&Schoolid=' + encodeURIComponent(SchoolId) +
'&SessionId=" ' + encodeURIComponent(SessionId) +
'&UnicodeValue=' + encodeURIComponent(UnicodeValue) +
'&ClassID=' + encodeURIComponent(ClassIdCommaSeparated.toString());
$.ajax({
url: s,
error: function(err) {
alert(err);
},
success: function(data) {....
}
});
Technically, both the name (before the =) and the value (after the =) need to be encoded, but when your names consist just of the letters A-Z (in upper or lower case) or digits, like yours do, encoding them doesn't change them at all. (If you didn't know what those names were, you'd definitely want to pass them through encodeURIComponent.)
several hours after i am not able to understand what is arising this problem.but i have worked around to have a temporary solution to the problem.i have used underscore in place of # and i got it working.thanks #T.J. Crowder for having a look upon.

How can I use the first entry of a JSON data array

I got this JSON as data:
data = {"livemode":false,"pending":
[{"amount":0,"currency":"jpy"},{"amount":8121,"currency":"usd"}],
"available":
[{"amount":-400,"currency":"jpy"},{"amount":99601,"currency":"usd"}]}
now I want to convert this into a more readable text something like this:
"Pending :" + "\n" + "Amount :" + data.pending[0].amount + "\n" + data.pending[0].currency;
So I want to give back the amount of 0 with the currency of jpy but all I get is an Error or undefined, what I'm doing wrong here?
onRetrieveBalancePressed : function() {
var that = this;
jQuery.ajax({
type : "GET",
contentType : "application/json",
url : "https:" + "/retrieve",
processData: true,
dataType : "text",
async: false,
success : function(data, textStatus, jqXHR) {
var sResult = "Balance successfully retrieved! \n"
+"Pending :" + "\n"
+"livemode :" + data.pending[0].amount + "\n"
+"Currency : " + data.pending[0].currency;
First just try to convert your data to JSON using
var obj = JSON.parse(data);
then try to get data from obj.
In case of jquery, you can also try this:
var obj = jQuery.parseJSON(data);
Try to use a JSONObject and put data in that obj then you can work more easily

Variable without value inside callback function

Im having a strange problem with the following code:
function getTrxData(trx,inputPar,outputPar,callback) {
var retorno = {};
var URL = '/XMII/Runner?Transaction=' + trx;
var params = "";
for(key in inputPar)
params = params + "&" + key + "=" + inputPar[key];
if(!outputPar)
outputPar = "*";
if(params)
URL = URL + params;
URL = URL + '&OutputParameter=' + outputPar;
$.ajax({
type: "GET",
url: URL,
async: true,
success: function(data){
retorno.datos = $.xml2json(data);
retorno.tipo = 'S'; // Success
retorno.mensaje = "Datos obtenidos correctamente";
callback(retorno);
},
error: function(jqXHR, textStatus, errorThrown){
retorno.tipo = 'E'; // Error
retorno.mensaje = "Error: " + textStatus;
callback(retorno);
}
});
}
function crearSelect(trx,inputPar,outputPar,selectID,campoTextoXX,campoValor,valorDefault,callback2) {
// At this point campoTextoXX exists and has a value
getTrxData(trx,inputPar,outputPar,function(retorno2) {
// At this point campoTextoXX is an object equal to callback2
if(retorno2.tipo == 'E') {
callback2(retorno2);
return false;
}
var options = "";
var selected = "";
$.each(retorno2.datos.Rowset.Row, function(k,v) {
if(valorDefault == v[campoValor]) {
selected = " selected='selected'";
} else {
selected = "";
}
options = options + "<option value='" + v[campoValor] + selected "'>";
options = options + v[campoTextoXX];
options = options + "</option>";
});
$("#" + selectID + " > option").remove();
$("#" + selectID).append(options);
callback2(retorno2);
});
}
And the call is like this:
crearSelect("Default/pruebas_frarv01/trxTest",{letra: 'V'},"*",'selectID',"CustomerID",'OrderID','',function(retorno) {
alert(retorno.tipo + ": " + retorno.mensaje);
});
The problem is that campoTextoXX and campoValor dont get any value inside the callback function. Also, debugging in Chrome shows me that campoTextoXX has the value of the callers callback function:
alert(retorno.tipo + ": " + retorno.mensaje);
I dont know what to do next.
Any ideas?
Thx
You might find it easier to mange the callback chain by exploiting $.ajax's ability to behave as a jQuery Deferred.
This allows us very simply to specify the "success" and "error" behaviour in the guise of request.done(...) and request.fail(...) at the point where getTrxData is called rather than inside getTrxData - hence the callback chain is (ostensibly) one level less deep.
function getTrxData(trx, inputPar, outputPar) {
inputPar.Transaction = trx;
inputPar.OutputParameter = (outputPar || '*');
return $.ajax({
url: '/XMII/Runner?' + $.param(inputPar)
});
}
function makeOptions(obj, selectID, campoTextoXX, campoValor, valorDefault) {
var $option, selected, $select = $("#" + selectID);
$("#" + selectID + " > option").remove();
$.each(obj.datos.Rowset.Row, function(k, v) {
selected = (valorDefault == v[campoValor]) ? ' selected="selected"' : '';
$option = $('<option value="' + v[campoValor] + selected + '">' + v[campoTextoXX] + "</option>");
$select.append($option);
});
return obj;
}
function crearSelect(trx, inputPar, outputPar, selectID, campoTextoXX, campoValor, valorDefault, callback) {
var request = getTrxData(trx, inputPar, outputPar);
request.done(function(data) {
var obj = {
datos: $.xml2json(data),
tipo: 'S',// Success
mensaje: "Datos obtenidos correctamente"
};
callback(makeOptions(obj, selectID, campoTextoXX, campoValor, valorDefault));
});
request.fail(function(jqXHR, textStatus, errorThrown) {
var obj = {
tipo: 'E',// Error
mensaje: "Error: " + textStatus
};
callback(obj);
});
}
crearSelect("Default/pruebas_frarv01/trxTest", {letra:'V'}, "*", 'selectID', "CustomerID", 'OrderID', '', function(retorno) {
alert(retorno.tipo + ": " + retorno.mensaje);
});
You will see that this is essentially a refactored version of your original code, with significant simplification of the string handling in getTrxData, which appears to work correctly.
The options code has been pulled out as a separate function, makeOptions, to make the new structure of crearSelect clearer. This is not strictly necessary and the code could be re-combined without penalty.
Tested here insomuch as to make sure it loads and runs through to the "Error" alert, which it does successfully. Without access to the server-side script, I can't test/debug the full ajax functionality so you may need to do some debugging.
The problem appears to be that you are overwriting the variable "pepe" somewhere in your code.
Also, check how you are assigning your callback function and parameter object. A quick look appears that it is not being supplied the correct parameters.
You should be careful not to use global variables within your success and error functions. so instead of:
success: function(data){
retorno.datos = $.xml2json(data);
retorno.tipo = 'S'; // Success
retorno.mensaje = "Datos obtenidos correctamente";
callback(retorno);
}
I think you should do something like:
success: function(data){
var retorno = {};
retorno.datos = $.xml2json(data);
retorno.tipo = 'S'; // Success
retorno.mensaje = "Datos obtenidos correctamente";
callback(retorno);
}
furthermore you should use Firebug for Firefox to step through your code and watch your variables to ensure that the data is coming in correctly, and not getting overwritten at any point
Your control flow is a bit confusing, and another thing you can do is check to make sure your callbacks and variables are correct using some typeof conditionals to make sure they are functions, etc. try doing things like this:
success: function(data){
var retorno = {};
retorno.datos = $.xml2json(data);
retorno.tipo = 'S'; // Success
retorno.mensaje = "Datos obtenidos correctamente";
if (typeof callback !== "function" || typeof data !== "object"){
console.log('error');
throw "callback or data is not correct type";
}
callback(retorno);
}
and make sure you aren't getting an error in the console.

How to access an object's contents in javascript?

When I do
$.each(result, function(i, n){
alert("key: " + i + ", Value: " + n );
});
then for each iteration I see
key: 276, Value: {"owners":["he"],"users":["he","m"],"end":"07/06-2011","groups":[],"type":"in"}
How do I access the values of owners, users, end, groups, and type for each iteration?
In Perl would I have done
foreach my $key (keys %result) {
print $result{$key}{owners};
print $result{$key}{users};
...
}
Update
I get result from JSON like so
$.ajax({
type: "GET",
url: "/cgi-bin/ajax.pl",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: { "cwis" : id },
// ...
success: function(result){
if (result.error) {
alert('result.error: ' + result.error);
} else {
$.each(result, function(i, n){
alert( "key: " + i + ", Value: " + n );
});
}
}
});
Update 2
It seams that the problem is the server side is not sending prober JSON.
This is the server side script that generate the JSON string.
!/usr/bin/perl -T
use CGI;
use CGI::Carp qw(fatalsToBrowser);
use CGI qw(:standard);
use JSON;
use utf8;
use strict;
use warnings;
my $cgi = CGI->new;
$cgi->charset('UTF-8');
my $json_string = qq{{"error" : "The user do not have any activities."}};
my $json = JSON->new->allow_nonref;
$json = $json->utf8;
# #a and $act is now available
my $data;
foreach my $id (#a) {
$data->{$id} = $json->encode(\%{$act->{$id}});
}
$json_string = to_json($data);
print $cgi->header(-type => "application/json", -charset => "utf-8");
print $json_string;
document.write(result[key].owners);
document.write(result[key].users);
UPDATE:
Apparently my comment on the question was the answer:
I'm no CGI expert but it looks like
you are double encoding your data into
JSON. Once with
my $json = JSON->new->allow_nonref; $json = $json->utf8;
and then again with
$data->{$id} = $json->encode(\%{$act->{$id}}) .
in $.each callbacks, this points to the current element, so
$.each(result, function(i, n){
alert(this.users);
});
n.owners or n['owners']
n.users or n['users']
etc.
In a loop...
$.each(result, function(k,v) {
console.log("key: " + k + ", value: " + v );
$.each(v, function(k,v)) {
console.log("key: " + k + ", value: " + v );
});
});
you can access them like this:
n.owners
or
n['owners']
or you can use another cycle :
$.each(result, function(i, n){
if (typeof(n)=='object') {
$.each(n, function(k, v){
alert('n.'+k+' = ' + v);
});
}
});
edit:
jsFiddle Example
Example 2
edit2: to avoid getting undefined make a simple check whether the key i is equal to "Value", so it's value will be an object

Categories