I was able to implement this using Javascript Promises (I haven't made this
a pull request because it's rather experimental):
emscripten_sync_wget2_data: function(url, request, param, arg, free,
onload, onerror, onprogress) {
var _url = Pointer_stringify(url);
var _request = Pointer_stringify(request);
var _param = Pointer_stringify(param);
var promise = new Promise(function(resolve, reject) {
var http = new XMLHttpRequest();
http.open(_request, _url, true);
http.responseType = 'arraybuffer';
// LOAD
http.onload = function http_onload(e) {
if (http.status == 200 || _url.substr(0,4).toLowerCase() != "http")
{
resolve(http.response);
}
else {
reject(http.status, http.statusText);
}
};
// ERROR
http.onerror = function http_onerror(e) {
reject(http.status, http.statusText);
};
// PROGRESS
http.onprogress = function http_onprogress(e) {
if (onprogress) Runtime.dynCall('viii', onprogress, [arg, e.loaded,
e.lengthComputable || e.lengthComputable === undefined ? e.total : 0]);
};
// Useful because the browser can limit the number of redirection
try {
if (http.channel instanceof Ci.nsIHttpChannel)
http.channel.redirectionLimit = 0;
} catch (ex) { /* whatever */ }
if (_request == "POST") {
//Send the proper header information along with the request
http.setRequestHeader("Content-type",
"application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", _param.length);
http.setRequestHeader("Connection", "close");
http.send(_param);
} else {
http.send(null);
}
});
promise.then(function(data) {
var byteArray = new Uint8Array(data);
var buffer = _malloc(byteArray.length);
HEAPU8.set(byteArray, buffer);
if (onload) Runtime.dynCall('viii', onload, [arg, buffer,
byteArray.length]);
if (free) _free(buffer);
}, function(status, statusText) {
if (onerror) Runtime.dynCall('viii', onerror, [arg, status,
statusText]);
});
},
Promises are still fairly new, and only supported by the most recent
versions of Chrome and Firefox, but they do give us the functionality we
want here. I think the best way to implement this in code would be if I
could use the C++ promise and future APIs. You can use these if you compile
with -std=c++11. All this seems to do at present is send the code into an
infinite loop, but if they could map into equivalent Javascript promise
calls, I think it could work quite well. At least in the case of
emscripten_sync_wget2_data, it could be set to use synchronous XHRs as a
fallback. This would still work, just require some extra conversion work,
and wouldn't call onprogress events.
On Sunday, March 16, 2014 7:17:56 PM UTC-7, Alon Zakai wrote:
>
> It can capture its environment, so you can put the second half of the
> function in a lambda, and call the lambda later on when you want to, in
> response to something.
>
> - Alon
>
>
>
> On Sun, Mar 16, 2014 at 7:12 PM, Joel Croteau <[email protected]<javascript:>
> > wrote:
>
>> I can understand using Javascript generators, but how would c++ lambdas
>> help?
>> On Mar 16, 2014 3:47 PM, "Alon Zakai" <[email protected] <javascript:>>
>> wrote:
>>
>>> Currently not. It would require a very different code generation
>>> approach than we currently have.
>>>
>>> In theory something similar could be done using generators, in very
>>> recent versions of firefox and chrome. But even with the help of
>>> generators, this is not easy to do, and it is not clear how it would affect
>>> performance - likely very adversely.
>>>
>>> One similar thing you can do is manage your own code using c++11
>>> lambdas. You could write a little system that continues to run the current
>>> function once a callback triggers that.
>>>
>>> - Alon
>>>
>>>
>>>
>>> On Sun, Mar 16, 2014 at 1:43 AM, Joel Croteau
>>> <[email protected]<javascript:>
>>> > wrote:
>>>
>>>> I would like to have a function that makes an async call, and returns
>>>> control to the browser during the call, then resumes once the async call
>>>> is
>>>> complete. However, I would like this to appear to the calling code to be a
>>>> synchronous call. So for instance, I could do something like this:
>>>>
>>>> struct FileInfo
>>>> {
>>>> void* buffer;
>>>> unsigned size;
>>>> };
>>>>
>>>> FileInfo loadUrl(const char* url)
>>>> {
>>>> FileInfo info;
>>>> emscripten_async_wget2_data(url, "GET", "", &info, false, onload,
>>>> onerror, onprogress);
>>>> emscripten_pause(); // Blocks until emscripten_resume() is called
>>>> return info;
>>>> }
>>>>
>>>> void onerror(void* ptr, int code, const char* desc)
>>>> {
>>>> // Handle not found, etc.
>>>> }
>>>>
>>>> void onprogress(void* ptr, int loaded, int total)
>>>> {
>>>> // Update progress bar
>>>> }
>>>>
>>>> void onload(void* ptr, void* buffer, unsigned size)
>>>> {
>>>> static_cast<FileInfo*>(ptr)->buffer = buffer;
>>>> static_cast<FileInfo*>(ptr)->size = size;
>>>>
>>>> emscripten_resume(); // Now loadUrl resumes and returns FileInfo.
>>>> }
>>>>
>>>> Is there any way to do this?
>>>>
>>>> --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "emscripten-discuss" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>> an email to [email protected]<javascript:>
>>>> .
>>>> For more options, visit https://groups.google.com/d/optout.
>>>>
>>>
>>> --
>>> You received this message because you are subscribed to a topic in the
>>> Google Groups "emscripten-discuss" group.
>>> To unsubscribe from this topic, visit
>>> https://groups.google.com/d/topic/emscripten-discuss/Op5ifeMjauA/unsubscribe
>>> .
>>> To unsubscribe from this group and all its topics, send an email to
>>> [email protected] <javascript:>.
>>>
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "emscripten-discuss" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected] <javascript:>.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>
--
You received this message because you are subscribed to the Google Groups
"emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.