How to deal with an event and make it synchronous?

1,566 views
Skip to first unread message

offshorewahoo

unread,
Feb 11, 2012, 5:21:00 PM2/11/12
to Oni Apollo & StratifiedJS
Perhaps this is elementary, but I need some help. Trying to work with
PhoneGap's FileReader object and obtain the text from a file
synchronously. Here is the same PhoneGap code:

function win(file) { var reader = new FileReader();
reader.onloadend = function(evt) { console.log("read
success"); console.log(evt.target.result); };
reader.readAsText(file);};var fail = function(evt)
{ console.log(error.code);};entry.file(win, fail);

The problem is that the text from the file comes in an event
(onloadend) and I can't figure out how to use something like waitfor()
to obtain the parameter that is passed to the onloadend function.

Any ideas?

Alexander Fritze

unread,
Feb 11, 2012, 6:26:38 PM2/11/12
to oni-a...@googlegroups.com
It's probably easiest to split this into two parts:

(1) retrieving a File object given a FileEntry
(2) reading the file contents from the File object

Let's start with (2):

function readFile(file) {


var reader = new FileReader();

waitfor(var evt) {
reader.onloaded = resume;
reader.readAsText(file);
}
return evt.target.result;
}

Notice how we declare 'evt' in the waitfor/resume's parentheses. This
parameter will automatically be bound when the 'resume' callback is
called.

Now (1):

function getFile(entry) {
waitfor(var rv, success) {
entry.file(function(file) { resume(file, true); },
function(err) { resume(err, false); });
}
if (!success) throw rv;
return rv;
}

Again, we declare the parameters returned through 'resume' in the
waitfor's parentheses. This time we need two parameters to distinguish
between the error case and the success case. In the error case, we
throw an exception.

With these two functions, you can now write synchronous code like this:

var file = getFile(entry);
var contents = readFile(file);
... do something with contents ...

For more waitfor()/resume examples, see e.g.
http://onilabs.com/presentations/ugent/suspend-events.html or
http://onilabs.com/presentations/ugent/retraction-xhr.html

Notice that the 'getFile' function above could be improved by adding
error handling and cancellation handling (the latter so that the file
read gets automatically aborted if the call is cancelled - see e.g.
the slides starting at
http://onilabs.com/presentations/ugent/cancellation.html ).

Cheers,
Alex

offshorewahoo

unread,
Feb 11, 2012, 6:09:07 PM2/11/12
to Oni Apollo & StratifiedJS
Apologies, my post should have said "Here is the *sample* PhoneGap
code..." And here is that sample code with better formatting:

function win(file) {
var reader = new FileReader();
reader.onloadend = function(evt) {
console.log("read success");
console.log(evt.target.result);
};
reader.readAsText(file);
}

;var fail = function(evt) {
console.log(error.code);
};

entry.file(win, fail);



I can get a valid file object using synchronous SJS code like this:



function getFileSync() {
waitfor(var fileSystem)
{ window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, resume); }
waitfor(var fileEntry) { fileSystem.root.getFile("myFile.txt",
null, resume); }
waitfor(var file) { fileEntry.file(resume, resume); }
var reader = new FileReader();
reader.onloadend = function(evt) {
console.log("read success");
console.log("file contents=" + evt.target.result);
}
waitfor() { reader.readAsText(file); }
console.log("zebra");
return reader.result;
}


This code works great all the way up to writing "read success" and
even the file contents to the console. But something goes wrong and
the final return statement does not get executed, nor does the text
"zebra" show up in the console. Why is that?

Alexander Fritze

unread,
Feb 11, 2012, 6:37:25 PM2/11/12
to oni-a...@googlegroups.com


I guess it's clear from the sample I just posted, but just for completeness:

You need to arrange for 'onloaded' to call 'resume' (either by setting
onloaded=resume, or by calling resume(..) from within the callback you
assign to onloaded). As 'resume' is only defined within the
waitfor()'s curlies, you also need to move the reader.onloaded
assignment into that block. Finally, to extract parameters that are
being passed into 'resume', you declare them in the waitfor()'s
parentheses.

Cheers,
Alex

offshorewahoo

unread,
Feb 11, 2012, 9:58:37 PM2/11/12
to Oni Apollo & StratifiedJS
Excuse my French, but wow, that crap really works! He he! Seriously,
I just had to modify "onloaded" to "onloadend" (missing an "n") and
bingo, it worked like a charm. Thanks a TON for that quick and expert
help. Here's to writing code that isn't a nightmare to write and
maintain! No kidding, this makes 75 lines of JS boil down to just 3
lines. Thanks again!
> >> Any ideas?- Hide quoted text -
>
> - Show quoted text -- Hide quoted text -
>
> - Show quoted text -

Rafa

unread,
Oct 2, 2012, 5:53:42 AM10/2/12
to oni-a...@googlegroups.com, ane...@certify.com
Hi,
I've got a similar problem, but I'm not being able to apply this solution. (You can see what I'm trying to do at the end of this thread: http://simonmacdonald.blogspot.com.es/2012/06/phongap-android-application-preferences.html ) The summary would be:

I want to retrieve the value of a saved preference calling this function:
myPreferenceValue = dime_pref ('colordefondo','white')

where:
function dime_pref (key,defecto) {
var resultado='Sin definir'

window.plugins.applicationPreferences.get(key, function(value) {
        console.log("El valor de la preferencia "+ key + " es = " + value)
        resultado = value
    }, function(error) {
        console.log(JSON.stringify(error))
        resultado = defecto
    });
   
return resultado
    }

The problem is that window.plugins.applicationPreferences.get works asynchronously, and even if it seems to work properly (because I can see the correct value in the console log), I don't get his value in the var resultado, because the program doesn't wait for it.

How should I use here  "waitfor" function?
Thanks in advance,
Rafa

Alexander Fritze

unread,
Oct 2, 2012, 5:04:45 PM10/2/12
to oni-a...@googlegroups.com
Hi Rafa,

Try something like this:

function dime_pref (key, defecto) {
var resultado;

waitfor () {
windows.plugins.applicationPreferences.get(
key,
function(value) { resultado = value; resume(); },
function(error) { resultado = defecto; resume(); }
)
}
return resultado;
}

Cheers,
Alex

rcere...@gmail.com

unread,
Oct 3, 2012, 6:16:35 AM10/3/12
to oni-a...@googlegroups.com
Alex, thank you very much for your answer. I'm afraid that I'm a little lost here because I didn't pay attention to the premises. Now I've noticed that the function waitfor() has something to do with Oni-Apollo, so I should install it previously.

Well, I inserted this line in my code:
<script type="text/javascript" charset="utf-8" src="oni-apollo.js"></script>
(in that file I have also <script type="text/javascript" charset="utf-8" src="cordova.js"></script>)

... thinking that that was enough. As it doesn't work (there's a syntax error pointing at the last bracket of " waitfor() { " )  I searched a little more and saw that there's also a server side... Here I'm completely lost.

Could you tell me what should I do to make it work? Is there also anything to be written in the java file that calls DroidGap,...?

Thanks again,
Rafa
Reply all
Reply to author
Forward
0 new messages