I', trying to do a emscripten_fetch() and always get a return value of 0. Not sure what is going on, I switched to a javascript version, which works but has it's own problems.
C++ - can anyone see what I'm doing wrong here? To me, it looks like the header data isn't getting set properly, as I get this error:
Uncaught TypeError: XMLHttpRequest.open: Cannot convert argument 1 to ByteString because the character at index 2 has value 56770 which is greater than 255.
Here is the code:
emscripten_fetch_attr_t attr;
emscripten_fetch_attr_init(&attr);
strcpy(attr.requestMethod, "POST");
attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY | EMSCRIPTEN_FETCH_WAITABLE;
const char *headers[] = {"Content-Type", "application/json", 0};
attr.requestHeaders = headers;
attr.requestData = request.c_str() ;
attr.requestDataSize = request.length() ;
qDebug("making fetch with URL: %s data: %s", req.c_str(), attr.requestData) ;
emscripten_fetch_t *fetch = emscripten_fetch(&attr, "http://172.23.4.90/jsonrpc"); // Blocks here until the operation is complete.
EMSCRIPTEN_RESULT ret = EMSCRIPTEN_RESULT_TIMED_OUT;
while(ret == EMSCRIPTEN_RESULT_TIMED_OUT)
{
// possibly do some other work;
ret = emscripten_fetch_wait(fetch, 5000) ; // milliseconds to wait, 0 to just poll, INFINITY=wait until completion
}
if (fetch->status == 200) {
qDebug("Finished downloading %llu bytes from URL %s.", fetch->numBytes, fetch->url);
// The data is now available at fetch->data[0] through fetch->data[fetch->numBytes-1];
retval.append(fetch->data, fetch->numBytes) ;
} else {
qDebug("Downloading %s failed, HTTP failure status code: %d.", fetch->url, fetch->status);
// throw jsonrpccxx::JsonRpcException(-32003, "client connector error, received status != 200");
}
emscripten_fetch_close(fetch);
I've tried with the wait, and a full sync with the same issue.
As a result, I then tried writing it in javascript, and magic, it works! console.log() put out the results I am expecting. But, all my C++ program gets back is an object promise. I'm not a Javascript guy, and don't know what's going on.
So, my questions:
does emscripten_fetch() work with POST header data?
Can someone show me a javascript (EM_JS) version that works?
Gerald
Related
I'm hoping someone can help with what is likely a simple answer - but I'm ready to bash my head against the wall....again.
I have a function which makes a JSON call to an API, and then pushes the results into an array. The function appears to work just fine as my console.log is showing that the array is populated correctly.
I'm struggling with how to access the values of the modified twichResult object (after the function has run), so that I can do 'stuff' with it. e.g. display the value of the 'status' property onscreen etc... I give some examples of what I've tried in the in the large commented out section.
I'd really appreciate some intelligence weighing in on this as I've exhausted my resources. Thanks in advance.
<script type="text/javascript">
$(document).ready(function() {
var twitchResult = {results:[]};
var channel = { logo:"", display_name:"", status:"", url:"" };
var finalUrl = "https://api.twitch.tv/kraken/streams/freecodecamp?callback=?"
getTwitchers (finalUrl, "freecodecamp");
console.log(twitchResult);
// How do I access the individual values in the object TwitchResult?
// I get "undefined" in the console if I try to access the object's property values
// I've tried every way I can think of to get 'into' the returned object :
// console.log(twitchResult.results);
// console.log(twitchResult["results"])
// console.log(twitchResult.results.status)
// console.log(twitchResult[0])
// console.log(twitchResult[0][0])
// etc etc
function getTwitchers (url, item) {
$.getJSON(url, function(data) {
var obj = data.stream;
// Check if the object is not valid using (obj == null) which is shorthand for both null and undefined
if (obj == null) {
if (obj === undefined) {
channel.display_name = item;
channel.status = "closed";
console.log ("this is undefined");
}
else {
channel.display_name = item;
channel.status = "offline";
console.log("this is null");
}
}
else {
channel.logo = obj.channel.logo;
channel.display_name = obj.channel.display_name;
channel.status = obj.channel.status;
channel.url = obj.channel.url;
console.log("valid entry");
}
twitchResult["results"].push(channel);
// twitchResult.results.push(channel);
// console.log(twitchResult);
});
}
});
</script>
$.getJSON is making an ajax-request. You must handle this request from within the request handler. When getTwichers returns, twichResults is not yet set.
There are methods to delay Program execution, until twichResults is done, but You should not think of using them, since they would delay program execution. The idea of ajax is to execute things asynchronously, without disturbing the rest of the execution flow. If the code You want to execute depends on the json, then You should add it to the handle in $.getJSON. Just write a new function (e.g. continue_execution(twichResult)) and invoke it right after twitchResult["results"].push(channel);. Just don't do anything after getTwitchers(...).
By the way: It is a good habit to define functions, before they are used, because it follows the flow the human eye reads the code and there are programming languages, which depend on this style of declaring function.
If this is unclear to You, then add a comment.
since a couple of hours ago all my parse functions have been returning invalid json. Nothing to do with the cloud code... I even tried rolling it back. I'm on the android platform and haven't made any game breaking changes to it..
For example,
I have a login function...
Parse.Cloud.define("loginuser", function(request, response){
var useremail = request.params.useremail;
var userpassword = request.params.userpassword;
var usersource = request.params.usersource;
Parse.User.logIn(useremail, userpassword,{
success:function(user){
// Sets either candidate or business to be true depending on condition
if (usersource == "candidate"){
user.set("candidate", true);
} else if (usersource == "business"){
user.set("business", true);
}
user.save(null, {
// login success & return
success: function(user){
response.success(user);
}, error: function(error){
response.error(error);
}
});
},
error:function(user, error){
// login failure
response.error(user, error);
}
});
});
With no change to it... it suddenly starts throwing error:
01-05 22:37:30.175 1052-1052/recruitr.recruitr E/Login error: com.parse.ParseRequest$ParseRequestException: bad json response
01-05 22:37:46.045 1052-1052/recruitr.recruitr E/Signup Error: com.parse.ParseRequest$ParseRequestException: bad json response
Does anyone know why?
EDIT:
Ran debugger and it pops this out when the error message shows up:
this = {LoginActivity$4#4619}
cancel = {boolean[1]#4623}
logincredentials = {HashMap#4624} size = 3
parseUser = null
e = {ParseRequest$ParseRequestException#4625} "com.parse.ParseRequest$ParseRequestException: bad json response"
isPermanentFailure = false
code = 100
cause = {JSONException#4630} "org.json.JSONException: Value <html> of type java.lang.String cannot be converted to JSONObject"
cause = {JSONException#4630} "org.json.JSONException: Value <html> of type java.lang.String cannot be converted to JSONObject"
detailMessage = {String#4638} "Value <html> of type java.lang.String cannot be converted to JSONObject"
stackState = {long[34]#4639}
stackTrace = {StackTraceElement[0]#4633}
suppressedExceptions = {Collections$EmptyList#4634} size = 0
shadow$_klass_ = {Class#497} "class org.json.JSONException"
shadow$_monitor_ = -1960135782
detailMessage = {String#4631} "bad json response"
stackState = {long[30]#4632}
stackTrace = {StackTraceElement[0]#4633}
suppressedExceptions = {Collections$EmptyList#4634} size = 0
shadow$_klass_ = {Class#4592} "class com.parse.ParseRequest$ParseRequestException"
shadow$_monitor_ = -2123277170
Found the problem:
The Android Parse SDK was having problems with a new update. Parse was not actually initializing in the code at all (keys weren't working/initialization was not working)
Fix the error by changing the dependency:
compile 'com.parse:parse-android:1.+'
to
compile 'com.parse:parse-android:1.12.0'
or
compile 'com.parse:parse-android:1.10.0'
Both seem to work flawlessly as of this moment in time.
Something about my use of chrome.hid.send seems to be leaving the bus in a bad state. I consistently can NOT get my second usage of the API call to work. Sometimes, it will also fail on the first usage. WITH THE EXACT SAME CODE, I can come back and try a while later (maybe 10min) and the first send will work.
The device I'm working with does not return a response to all messages sent to it. The test message for example, is just a dummy message that is ignored by the device. I've tested this both on a mac and a PC. My call stack depth is 2 at this point in my application (literally first one is kicked off by a button click and then a setTimeout calls the same method 5s later).
I've testing sending buffers of length 64Bytes as well as 58Bytes. The properties from the HidDeviceInfo object read "maxInputReportSize":64,"maxOutputReportSize":64
Params on first usage:
Params on second usage:
I really can't identify how I'm using the API incorrectly. When messages do succeed, I can see them on the device side.
// Transmits the given data
//
// #param[in] outData, The data to send as an ArrayBuffer
// #param[in] onTxCompleted, The method called on completion of the outgoing transfer. The return
// code is passed as a string.
// #param[in] onRxCompleted, The method called on completion of the incoming transfer. The return
// code is passed as a string along with the response as an ArrayBuffer.
send: function(outData, onTxCompleted, onRxCompleted) {
if (-1 === connection_) {
console.log("Attempted to send data with no device connected.");
return;
}
if (0 == outData.byteLength) {
console.log("Attempted to send nothing.");
return;
}
if (COMMS.receiving) {
console.log("Waiting for a response to a previous message. Aborting.");
return;
}
if (COMMS.transmitting) {
console.log("Waiting for a previous message to finish sending. Aborting.");
return;
}
COMMS.transmitting = true;
var dummyUint8Array = new Uint8Array(outData);
chrome.hid.send(connection_, REPORT_ID, outData, function() {
COMMS.transmitting = false;
if (onTxCompleted) {
onTxCompleted(chrome.runtime.lastError ? chrome.runtime.lastError.message : '');
}
if (chrome.runtime.lastError) {
console.log('Error in COMMS.send: ' + chrome.runtime.lastError.message);
return;
}
// Register a response handler if one is expected
if (onRxCompleted) {
COMMS.receiving = true;
chrome.hid.receive(connection_, function(reportId, inData) {
COMMS.receiving = false;
onRxCompleted(chrome.runtime.lastError ? chrome.runtime.lastError.message : '', inData);
});
}
});
}
// Example usage
var testMessage = new Uint8Array(58);
var testTransmission = function() {
message[0] = 123;
COMMS.send(message.buffer, null, null);
setTimeout(testTransmission, 5000);
};
testTranmission();
The issue is that Windows requires buffers to be the full report size expected by the device. I have filed a bug against Chromium to track adding a workaround or at least a better error message to pinpoint the problem.
In general you can get more detailed error messages from the chrome.hid API by enabling verbose logging with the --enable-logging --v=1 command line options. Full documentation of Chrome logging is here.
Im trying to send a push message to everyone with read access every time a new note is saved.
In pseudocode it should get the ACL. Evaluate each member in the ACL and return an array of all users with read access. Then send a push notification to each member.
I've tried running separate task one by one and it works properly. However when I put everything together in the following code I get strange results. Looking at the log I can see it not executing in order as I expect. I first though the getACL call was an asynchronous call so I tried to implement promises with no luck. Then after help from stackoverflow I find out that getACL is not asynchronous therefore the code should just work, right?
This is what I'm trying:
Parse.Cloud.afterSave("Notes", function(request) {
var idsToSend = [];
var i = 0;
console.log("1 start");
var objACL = request.object.getACL();
var ACLinJSON = objACL.toJSON();
console.log("2 ACL = " + ACLinJSON);
for (var key in ACLinJSON) {
if (ACLinJSON[key].read == "true") {
idsToSend[i] = key.id;
console.log("3 i = " + i + " = " + idsToSend[i]);
i++;
}
}
console.log("4 idsToSend = " + idsToSend);
//lookup installations
var query = new Parse.Query(Parse.Installation);
query.containedIn('user', idsToSend);
Parse.Push.send({
where: query,
data: {
alert: "note updated"
}
}, {
success: function() {
console.log("Success sent push");
},
error: function(error) {
console.error("can’t find user"); //error
}
});
});
And this is the response I see from parse log
I2014-08-04T08:08:06.708Z]4 idsToSend =
I2014-08-04T08:08:06.712Z]2 ACL = [object Object]
I2014-08-04T08:08:06.714Z]1 start
I2014-08-04T08:08:06.764Z]Success sent push
Everything is completely out of order??
How can I execute the above function in the way it's written?
I've found the logs are not in order when I run things too, could be a timing issue or something, ignore the order when they're in the same second, I have done other tests to confirm things really do run in order on my own Cloud Code... had me completely confused for a while there.
The issue you're having is that log #3 is never being hit... try tracing ACLinJSON on it's own to see the actual structure. When you append it to a string it outputs [object Object] as you have seen, so do console.log(ACLinJSON); instead.
Here's the structure I've seen:
{
"*":{"read":true},
"Administrator":{"write":true}
}
Based on that I would expect your loop to work, but it may have a different level of wrapping.
UPDATE:
Turns out the issue was looking for the string "true" instead of a boolean true, thus the fix is to replace the following line:
// replace this: if (ACLinJSON[key].read == "true") {
if (ACLinJSON[key].read == true) {
My javascript:
var params = {};
params.selectedCurrency = 'USD';
params.orderIdForTax = '500001';
var xhrArgs1 = {
url : 'UpdateCurrencyCmd',
handleAs : 'text',
content : params,
preventCache:false,
load:function(data){
alert('success!');
},
error: function(error){
alert(error);
//the alert says 'SyntaxError: syntax error'
},
timeout:100000
};
dojo.xhrPost(xhrArgs1);
I tried debugging with firebug, i do get the appropriate response (i think). Here it is;
/*
{
"orderIdForTax": ["500001"],
"selectedCurrency": ["USD"]
}
*/
The comments /* and */ are somehow embedded automatically cuz the url im hitting with xhrPost is actually a command class on ibm's websphere commerce environment. Can anyone tell me what am i doing wrong here?
Server code
public void performExecute() throws ECException {
try{
super.performExecute();
double taxTotal;
System.out.println("Updating currency in UpdateCurrencyCmd...");
GlobalizationContext cntxt = (GlobalizationContext) getCommandContext().getContext(GlobalizationContext.CONTEXT_NAME);
if(requestProperties.containsKey("selectedCurrency"))
selectedCurrency = requestProperties.getString("selectedCurrency");
else
selectedCurrency = cntxt.getCurrency();
if(requestProperties.containsKey("orderIdForTax"))
orderId = requestProperties.getString("orderIdForTax");
OrderAccessBean orderBean = new OrderAccessBean();
cntxt.setCurrency(selectedCurrency.toUpperCase());
orderBean.setInitKey_orderId(orderId);
orderBean.refreshCopyHelper();
orderBean.setCurrency(selectedCurrency.toUpperCase());
orderBean.commitCopyHelper();
TypedProperty rspProp = new TypedProperty();
rspProp.put(ECConstants.EC_VIEWTASKNAME, "AjaxActionResponse");
setResponseProperties(rspProp);
}catch(Exception e){
System.out.println("Error: " + e.getMessage() );
}
}
The problem was with my client side code, weirdly.
load:function(data){
data = data.replace("/*", "");
data = data.replace("*/", "");
var obj = eval('(' + data + ')');
alert('Success');
}
Its weird but this worked. Lol.
I guess the problem is with coment-filtering option of handle as method.
The response should be comment filered as below.
See tha AjaxActionResponse.jsp (WCS)
vailable Handlers
There are several pre-defined contentHandlers available to use. The value represents the key in the handlers map.
text (default) - Simply returns the response text
json - Converts response text into a JSON object
xml - Returns a XML document
javascript - Evaluates the response text
json-comment-filtered - A (arguably unsafe) handler to preventing JavaScript hijacking
json-comment-optional - A handler which detects the presence of a filtered response and toggles between json or json-comment-filtered appropriately.
Examples