How to catch exceptions With WebOS' AjaxCall - webos

I'm developing a WebOS 2.x app with mojo framework. I use Foundations.Comms.AjaxCall to make ajax request. It goes well when everything is OK. However, when the call fails or the server response an error, I can't catch the error information.
I have tried this:
var f = AjaxCall.get(url);
f.then(successHandler, failureHandler);
and this:
var f = AjaxCall.get(url);
f.onError(failureHandler);
f.then(successHandler);
neither of them works. failureHandler is never called when there is an error.
Is there any way to be informed when there is an error?

In my Mojo apps I used Ajax.Request
I defined the onComplete handler like this:
onComplete: function(resp) {
var resultCode = resp.getStatus();
if ((resultCode > 0) && (resultCode < 200)) {
...
} else {
...
}

Related

How to update an User with useMasterKey in Parse

Issue Description
I'm trying to update an User when another user click on my Xamarin button.
Then, I used Cloud Code to perform this but it doesnt work
My Code
Here is my complete JS code :
Parse.Cloud.beforeSave("Archive", function(request, response) {
Parse.serverURL = 'https://pg-app-0brffxkawi8lqvf2eyc2isqrs66zsu.scalabl.cloud/1/';
var status = request.object.get("status");
if (status == "validated") {
var event = request.object.get("event");
event.fetch({
success: function(myEvent) {
var coinsEvent = myEvent.get("coins");
var user = request.object.get("user");
user.fetch({
success: function(myUser, coinsEvent, user) {
var email = myUser.get("email");
var coinsUser = myUser.get("coins");
myUser.set("coins", coinsUser + coinsEvent);
return myUser.save(null, {useMasterKey:true});
}
});
}
});
}
response.success();
});
I think myUser.save(null, {useMasterKey:true}); should work
I actually have that error :
Dec 24, 2017, 12:27 GMT+1 - ERRORError generating response for [PUT] /1/classes/_User/1GPcqmn6Hd
"Cannot modify user 1GPcqmn6Hd."
{
"coins": 250
}
Environment Setup
Server
parse-server version : v2.3.3
Server: Sashido
Your success branch never calls response.success() which is a problem... though maybe not THE problem.
You are also doing 2 fetches inside a 'beforeSave' function which is not recommended. 'BeforeSave' must happen very quickly and fetches take time. I would consider thinking through other options.
If you really need to do it this way, consider doing a Parse.Query("event") with an include("user") and trigger the query with query.first({useMasterKey:true}).
Are you sure coinsEvent is what you think it is? Fetch only returns the object fetched... not sure that you can curry in other parameters. I would change your final success routine to (double checking that coinsEvent is valid):
success: function(myUser) {
var coinsUser = myUser.get("coins");
myUser.set("coins", coinsUser + coinsEvent);
return myUser.save(null, {useMasterKey:true}).then(_ => response.success());
}

Worker thread issue with postMessage()

In the worker thread, when I call postMessage() to send message back to the main thread - it's not allowing a single argument signature.
e.g. postMessage( { success: true } );
VisualCode is displaying a required signature of postMessage(any, string, transfer? );
I've got require('globals'); at the top of the worker file.
This is what I have so far:
require('globals'); // necessary to bootstrap tns modules on the new thread
onmessage = function(msg)
{
var request = msg.data;
var data = request.data;
var result = "OK";
var message : any = result !== undefined ? { success: true, src: result } : { };
postMessage( message ); // << problem
}
It's a little workaround, however I managed to fix it in my app by adding re-declared function signature in the beggining of the worker file like this:
declare function postMessage(message: any);
Hope it helps.
It is important to mention that the error you are seeing is most likely a compilation error as a result of using TypeScript.
The nativescript workers implementation should only take one argument as of the current version.
Add reference to node_modules/tns_core_modules/webworker.es2016.d.ts as they contain the proper definition

socketio client: How to handle socketio server down

I've got a socketio server/client working well together, however I want to start writing events for when the server is offline on page load or during normal run.
I'm including the remote socket.io code in my header:
<script src="<?=NODE_HOST?>/socket.io/socket.io.js"></script>
<script>
var nodeHost = '<?=NODE_HOST?>';
</script>
And in my client controller I have
if(typeof io != 'undefined')
this.socket = io.connect(this.settings.server);
else
this.handleDisconnect();
The function I have to attempt to re-connect over and over if a) A socket disconnect occurs during normal operation, or b) the server is down on page load
botController.prototype.handleDisconnect = function() {
$.getScript(nodeHost+"/socket.io/socket.io.js").done(function(script, textStatus) {
bot.control.socket = io.connect(bot.control.settings.server);
}).fail(function(jqxhr, settings, exception) {
setTimeout(function() {
bot.control.handleDisconnect();
}, 5000);
});
}
Am I going about this the correct way?
The main issue I have right now (which made me create this question) is my code errors on page load when the server is down because I have functions like:
socket.on(...
When socket doesn't yet exist. I could wrap those in a function and call it when I detect the global socket object exists on successful reconnection? Would it matter if that function that contains socket.on... is called multiple times (if the server goes down more than once during operation)?
OK I managed to come up with this solution that seems to work well using yepnope which I already had using Modernizr (it handles the cross domain issue for me too).
<script src="<?=NODE_HOST?>/socket.io/socket.io.js"></script>
<script>
var nodeHost = '<?=NODE_HOST?>';
</script>
// Attempt to connect to nodejs server
botController.prototype.start = function() {
// Is our nodejs server up yet?
if(typeof io != 'undefined') {
this.socket = io.connect(this.settings.server);
this.startSocketEvents();
} else {
this.handleDisconnect();
}
}
// Our connection to the server has been lost, we need to keep
// trying to get it back until we have it!
botController.prototype.handleDisconnect = function(destroySocketObject) {
if(destroySocketObject === undefined)
destroySocketObject = true;
// Destroy any cached io object before requesting the script again
if(destroySocketObject)
io = undefined;
yepnope.injectJs(nodeHost+"/socket.io/socket.io.js",
function(result) {
// Did it actually download the script OK?
if(typeof io != 'undefined') {
bot.control.socket = io.connect(bot.control.settings.server);
bot.control.startSocketEvents();
} else {
setTimeout(function() {
bot.control.handleDisconnect(false);
}, 5000);
}
}
);
Where startSocketEvents() function contains all of my socket.on events

KnockoutJS with IE8, occasional problems with Stringify?

A number of our users are still on IE8. Some of them occasionally are reporting problems when trying to post data to our servers (via a big button labeled "SAVE").
There is a script error that IE8 shows, which is: Unexpected call to method or property access, always pointing to the same line in the KnockoutJS 2.2.0 (debug, for now) library, line 450, which is as follows:
return JSON.stringify(ko.utils.unwrapObservable(data), replacer, space);
The method in my code that is at the root of the stack trace where this happens is this:
self.saveSingle = function (onSuccess, onFailure) {
ko.utils.arrayForEach(self.days(), function (day) {
day.close();
});
var jsonData = ko.toJSON(self);
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: applicationLocation + "/api/assignmentapi/save",
data: jsonData,
success: function (data) {
self.status(data.Status);
self._isDirty(false);
ko.utils.arrayForEach(self.days(), function (day) {
day.clean();
});
if (onSuccess)
onSuccess();
},
error: function (data) {
onFailure();
},
dataType: "json"
});
};
We do strip out a number of properties that are not necessary to our POST as we convert the object to JSON, using this approach: http://www.knockmeout.net/2011/04/controlling-how-object-is-converted-to.html
OurType.prototype.toJSON = function () {
var copy = ko.toJS(this);
delete copy.someUnneededProperty1;
delete copy.someUnneededProperty2;
delete copy.someUnneededProperty3;
delete copy.someUnneededProperty4;
return copy;
}
When it fails, it fails consistently on the line
var jsonData = ko.toJSON(self);
Now here comes the real mess:
It's not consistently happening
It doesn't happen to all IE8 users
We can't consistently reproduce it
The structure of our model that we're serializing doesn't appear matter
The jscript.dll is the current version for IE8
I was also experiencing this issue. Digging deeper I found a few things:
It was only failing occasionally, I found this by running the code in the console
The code in the data-bind was trowing an exception except the message was being swallowed due to IE8 gobbling up the message when using a try {} finally {} block (without catch).
Removing the try finally revealed a cannot parse bindings message.
When I started to get close to figuring out the issue (digging deep into the knockout code) it seemed to disappear in front of my eyes. This is the section of code it was failing on, catching the exception at the end of the code:
ko.utils.extend(ko.bindingProvider.prototype, {
'nodeHasBindings': function(node) {
switch (node.nodeType) {
case 1: return node.getAttribute(defaultBindingAttributeName) != null; // Element
case 8: return ko.virtualElements.virtualNodeBindingValue(node) != null; // Comment node
default: return false;
}
},
'getBindings': function(node, bindingContext) {
var bindingsString = this['getBindingsString'](node, bindingContext);
return bindingsString ? this['parseBindingsString'](bindingsString, bindingContext, node) : null;
},
// The following function is only used internally by this default provider.
// It's not part of the interface definition for a general binding provider.
'getBindingsString': function(node, bindingContext) {
switch (node.nodeType) {
case 1: return node.getAttribute(defaultBindingAttributeName); // Element
case 8: return ko.virtualElements.virtualNodeBindingValue(node); // Comment node
default: return null;
}
},
// The following function is only used internally by this default provider.
// It's not part of the interface definition for a general binding provider.
'parseBindingsString': function(bindingsString, bindingContext, node) {
try {
var bindingFunction = createBindingsStringEvaluatorViaCache(bindingsString, this.bindingCache);
return bindingFunction(bindingContext, node);
} catch (ex) {
throw new Error("Unable to parse bindings.\nMessage: " + ex + ";\nBindings value: " + bindingsString);
}
}
});
But yea, it stopped becoming reproducible so I came up with a hack that I tested and works earlier, just retrying the data parsing. So this:
data-bind="value: ko.computed(function(){return ko.toJSON(appViewModel.model()[0])})"
Became this:
data-bind="value: ko.computed(function(){while (true) { try { var json = ko.toJSON(appViewModel.model()[0]); return json; }catch(e){}}})"
Yes, it's very yucky, but it seems to do the trick until our users no longer need IE8 or the Knockout issue is fixed.
I have no idea if this will fix it, but you can use the mapping plugin to go between JS and JSON:
var mapping = {
'ignore': ["propertyToIgnore", "alsoIgnoreThis"]
}
var viewModel = ko.mapping.toJS(data, mapping);
Taken from my answer to this question
I'd give this a try and see if it helps, as there's nothing obviously wrong in your approach.
Are you sure it's IE8 users who are hitting the issue? IE7 does not support JSON.stringify. You'll need to include the json2.js library to support IE7 and lower.

Receiving binary data using request module in Firefox Add-on SDK

I am using the Add-on builder and I need to receive binary data (image). I would like to do this using the request module but as you can see from the documentation:
https://addons.mozilla.org/en-US/developers/docs/sdk/latest/packages/addon-kit/docs/request.html
There are only text and json properties and raw is absent.
How should I receive binary data in the add-on script?
You cannot do this using the request module, you will have to use the regular XMLHttpRequest via chrome authority. Something like this should work:
var {Cc, Ci} = require("chrome");
var request = Cc["#mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Ci.nsIJSXMLHttpRequest);
request.open("GET", "...");
request.onload = function()
{
onUnload.unload();
var arrayBuffer = request.response;
if (arrayBuffer)
{
var byteArray = new Uint8Array(arrayBuffer);
...
}
};
request.onerror = function()
{
onUnload.unload();
}
request.send(null);
var onUnload = {
unload: function()
{
// Make sure to abort the request if the extension is disabled
try
{
request.abort();
}
catch (e) {}
}
};
require("unload").ensure(onUnload);
The mechanism to ensure that the request is aborted if your extension is suddenly disabled is rather awkward, that's the main reason the request module exists rather than simply giving you XMLHttpRequest. Note that it is important to call onUnload.unload() once the request finishes, otherwise the Add-on SDK will keep it in the list of methods to be called on unload (a memory leak). See documentation of unload module.

Resources