getting result of async streamMessage - Mozilla

This is a discussion on getting result of async streamMessage - Mozilla ; Hello, I'm kind of stuck once again. So far I've read the content of an email synchronous. However there are those emails with big attachments, which then result in these 'Stop script' prompts and several seconds wait for the user ...

+ Reply to Thread
Results 1 to 4 of 4

Thread: getting result of async streamMessage

  1. getting result of async streamMessage

    Hello,
    I'm kind of stuck once again. So far I've read the content of an email
    synchronous. However there are those emails with big attachments,
    which then result in these 'Stop script' prompts and several seconds
    wait for the user so I thought about making it asynchronous. That
    worked all righ, however I don't get the result as I wanted. While the
    async Stream is reading, I wanted to do a bit and eventually open a
    dialog, in which the user gets to perform a few actions. Once he
    clicks on OK, I need the complete email to perform a few actions on
    it. It is no problem with the usual small mails, however with these
    big mails, I don't know how to tell TB to check whether the final
    result is there every few milliseconds. Using a While-Solution freezes
    everything as the CPU is busy working on the While-part. I then read a
    bit along and found setTimeout() and setIntervall() as was proposed in
    other forums.
    Here my code: I'll explain what I tried out so far afterwards.

    var msg_service = messenger.messageServiceFromURI(uri);
    var msg_stream = AsyncStream();
    try {
    msg_service.streamMessage(uri, msg_stream, msgWindow, null,
    false, null);
    }catch (ex) {
    log(ex)
    }
    /*do something*/
    var params = {inn:{msg_stream:msg_stream}, out:null};
    window.openDialog("chrome://test/content/dialog.xul","test-
    dialog","chrome, dialog, modal",params).focus();
    }

    function AsyncStream() {
    var aListener = {
    _first: true,
    _data: null,
    _finaldata: null,

    QueryInterface : function(iid) {
    if (iid.equals
    (Components.interfaces.nsIStreamListener) ||
    iid.equals
    (Components.interfaces.nsIMsgHeaderSink) ||
    iid.equals(Components.interfaces.nsISupports))
    {
    return this;
    } else {
    throw Components.results.NS_NOINTERFACE;
    return 0;
    }
    },

    onStartRequest : function (aRequest, aContext) {
    },

    onStopRequest : function (aRequest, aContext, aStatusCode)
    {
    this._finaldata = this._data;
    },

    onDataAvailable : function (aRequest, aContext,
    aInputStream, aOffset, aCount) {
    var binInputStream = Components.classes["@mozilla.org/
    binaryinputstream;1"].createInstance
    (Components.interfaces.nsIBinaryInputStream);
    binInputStream.setInputStream(aInputStream);
    if (this._first) {
    this._data = binInputStream.readBytes
    (binInputStream.available());
    this._first = false;
    } else{
    this._data += binInputStream.readBytes
    (binInputStream.available());
    binInputStream.close();
    }
    },
    };
    return aListener;
    }

    The code from the dialog:

    custombutton_accept = function(){
    msg_stream = window.arguments[0].inn.msg_stream;
    var lade = window.setInterval("wait_until_finished(msg_stream)",
    500);

    function wait_until_finished(stream){
    if(stream._finaldata){
    log(stream._finaldata);
    window.clearInterval(lade);
    get_body(stream._finaldata);
    }
    };

    function get_body(body){
    alert(body);
    return true;
    };

    return true;
    }

    Since I want to check every x ms I tried using setInterval, however
    the dialog simply gets closed as the code isn't stopped after
    setInterval, instead it simply continues and closes the dialog. I
    waited a bit to see if afterwards something happened but there never
    came anything.

    I also tried setTimeout:

    custombutton_accept = function(){
    msg_stream = window.arguments[0].inn.msg_stream;
    wait_until_finished(msg_stream);
    }

    wait_until_finished = function(stream){
    if(stream._finaldata){
    log(stream._finaldata);
    get_body(stream._finaldata);
    }else{
    window.setTimeout("wait_until_finished(stream)",500);
    }
    }

    get_body = function(body){
    /*do something*/
    alert(body);
    }

    Same problem as with setInterval.

    A combination of while and setInterval:

    wait_until_finished = function(stream){
    while( !stream._finaldata() ){
    setTimeout('wait_until_finished(stream)', 100)
    }
    get_body(stream._finaldata());
    }
    This froze the ui as if you just used while, since the code doesn't
    stop after setInterval.

    I don't know what else to try. Any tipps/hints/code examples are
    greatly appreciated.

    Greetings,
    Serratia

  2. Re: getting result of async streamMessage

    On Mar 23, 3:03*pm, "Red_Serra...@hotmail.de"
    wrote:
    > Hello,
    > I'm kind of stuck once again. So far I've read the content of an email
    > synchronous. However there are those emails with big attachments,
    > which then result in these 'Stop script' prompts and several seconds
    > wait for the user so I thought about making it asynchronous. That
    > worked all righ, however I don't get the result as I wanted. While the
    > async Stream is reading, I wanted to do a bit and eventually open a
    > dialog, in which the user gets to perform a few actions. Once he
    > clicks on OK, I need the complete email to perform a few actions on
    > it. It is no problem with the usual small mails, however with these
    > big mails, I don't know how to tell TB to check whether the final
    > result is there every few milliseconds. Using a While-Solution freezes
    > everything as the CPU is busy working on the While-part. I then read a
    > bit along and found setTimeout() and setIntervall() as was proposed in
    > other forums.
    > Here my code: I'll explain what I tried out so far afterwards.
    >
    > var msg_service = messenger.messageServiceFromURI(uri);
    > var msg_stream = AsyncStream();
    > try {
    > * * *msg_service.streamMessage(uri, msg_stream, msgWindow, null,
    > false, null);}catch (ex) {
    > * * *log(ex)
    > }
    >
    > /*do something*/
    > var params = {inn:{msg_stream:msg_stream}, out:null};
    > window.openDialog("chrome://test/content/dialog.xul","test-
    > dialog","chrome, dialog, modal",params).focus();
    >
    > }
    >
    > function AsyncStream() {
    > * * * var aListener = {
    > * * * * * * * * * * * * _first: true,
    > * * * * * * * * * * * * _data: null,
    > * * * * * * * * * * * * _finaldata: null,
    >
    > * * * * * * QueryInterface : function(iid) *{
    > * * * * * * * * if (iid.equals
    > (Components.interfaces.nsIStreamListener) ||
    > * * * * * * * * * * *iid.equals
    > (Components.interfaces.nsIMsgHeaderSink) ||
    > * * * * * * * * * * * * iid.equals(Components.interfaces.nsISupports))
    > {
    > * * * * * * * * * * return this;
    > * * * * * * * * } else {
    > * * * * * * * * * * throw Components.results.NS_NOINTERFACE;
    > * * * * * * * * * * return 0;
    > * * * * * * * * }
    > * * * * * * },
    >
    > * * * * * * onStartRequest : function (aRequest, aContext) {
    > * * * * * * },
    >
    > * * * * * * onStopRequest : function (aRequest, aContext, aStatusCode)
    > {
    > * * * * * * * * this._finaldata = this._data;
    > * * * * * * },
    >
    > * * * * * * onDataAvailable : function (aRequest, aContext,
    > aInputStream, aOffset, aCount) {
    > * * * * * * * * var binInputStream = Components.classes["@mozilla.org/
    > binaryinputstream;1"].createInstance
    > (Components.interfaces.nsIBinaryInputStream);
    > * * * * * * * * binInputStream.setInputStream(aInputStream);
    > * * * * * * * * if (this._first) {
    > * * * * * * * * * * * this._data = binInputStream..readBytes
    > (binInputStream.available());
    > * * * * * * * * * * * this._first = false;
    > * * * * * * * * } else{
    > * * * * * * * * * this._data += binInputStream.readBytes
    > (binInputStream.available());
    > * * * * * * * * * *binInputStream.close();
    > * * * * * * * *}
    > * * * * * * },
    > * * * * };
    > * * * * return aListener;
    >
    > }
    >
    > The code from the dialog:
    >
    > custombutton_accept = function(){
    > * msg_stream = window.arguments[0].inn.msg_stream;
    > * var lade = window.setInterval("wait_until_finished(msg_stream)",
    > 500);
    >
    > * function wait_until_finished(stream){
    > * * if(stream._finaldata){
    > * * *log(stream._finaldata);
    > * * *window.clearInterval(lade);
    > * * *get_body(stream._finaldata);
    > * * }
    > * };
    >
    > * function get_body(body){
    > * *alert(body);
    > * *return true;
    > * };
    >
    > * return true;
    >
    > }
    >
    > Since I want to check every x ms I tried using setInterval, however
    > the dialog simply gets closed as the code isn't stopped after
    > setInterval, instead it simply continues and closes the dialog. I
    > waited a bit to see if afterwards something happened but there never
    > came anything.
    >
    > I also tried setTimeout:
    >
    > custombutton_accept = function(){
    > * msg_stream = window.arguments[0].inn.msg_stream;
    > * wait_until_finished(msg_stream);
    >
    > }
    >
    > wait_until_finished = function(stream){
    > * if(stream._finaldata){
    > * * log(stream._finaldata);
    > * * get_body(stream._finaldata);
    > * }else{
    > * * window.setTimeout("wait_until_finished(stream)",500);
    > * }
    >
    > }
    >
    > get_body = function(body){
    > * /*do something*/
    > * alert(body);
    >
    > }
    >
    > Same problem as with setInterval.
    >
    > A combination of while and setInterval:
    >
    > wait_until_finished = function(stream){
    > * *while( !stream._finaldata() ){
    > * * * *setTimeout('wait_until_finished(stream)', 100)
    > * *}
    > * *get_body(stream._finaldata());}
    >
    > This froze the ui as if you just used while, since the code doesn't
    > stop after setInterval.
    >
    > I don't know what else to try. Any tipps/hints/code examples are
    > greatly appreciated.
    >
    > Greetings,
    > Serratia


    I think it's best to use the event queue service object instead of
    setting timeouts which pretty much stalls the entire UI thread while
    still being mixed in with current browser thread: @mozilla.org/event-
    queue-service

    ----------------------------------8<----------------------------------
    Components.classes["@mozilla.org/event-queue-service;1"].getService
    (Components.interfaces.nsIEventQueueService)
    ---------------------------------->8----------------------------------

    And use an asynchrounous request to resolve it, but you'll have to
    embed the listener in the object while resolving it so that it can
    notify the listener when data is available, or stopped. Like:
    onDataAvailable.

    Please correct me if I'm wrong or don't understand your question
    properly.

    /rvdh

  3. Re: getting result of async streamMessage

    On 24 Mrz., 10:22, 0x000000 wrote:
    > On Mar 23, 3:03*pm, "Red_Serra...@hotmail.de"
    >
    >
    >
    > wrote:
    > > Hello,
    > > I'm kind of stuck once again. So far I've read the content of an email
    > > synchronous. However there are those emails with big attachments,
    > > which then result in these 'Stop script' prompts and several seconds
    > > wait for the user so I thought about making it asynchronous. That
    > > worked all righ, however I don't get the result as I wanted. While the
    > > async Stream is reading, I wanted to do a bit and eventually open a
    > > dialog, in which the user gets to perform a few actions. Once he
    > > clicks on OK, I need the complete email to perform a few actions on
    > > it. It is no problem with the usual small mails, however with these
    > > big mails, I don't know how to tell TB to check whether the final
    > > result is there every few milliseconds. Using a While-Solution freezes
    > > everything as the CPU is busy working on the While-part. I then read a
    > > bit along and found setTimeout() and setIntervall() as was proposed in
    > > other forums.
    > > Here my code: I'll explain what I tried out so far afterwards.

    >
    > > var msg_service = messenger.messageServiceFromURI(uri);
    > > var msg_stream = AsyncStream();
    > > try {
    > > * * *msg_service.streamMessage(uri, msg_stream, msgWindow, null,
    > > false, null);}catch (ex) {
    > > * * *log(ex)
    > > }

    >
    > > /*do something*/
    > > var params = {inn:{msg_stream:msg_stream}, out:null};
    > > window.openDialog("chrome://test/content/dialog.xul","test-
    > > dialog","chrome, dialog, modal",params).focus();

    >
    > > }

    >
    > > function AsyncStream() {
    > > * * * var aListener = {
    > > * * * * * * * * * * * * _first: true,
    > > * * * * * * * * * * * * _data: null,
    > > * * * * * * * * * * * * _finaldata: null,

    >
    > > * * * * * * QueryInterface : function(iid) *{
    > > * * * * * * * * if (iid.equals
    > > (Components.interfaces.nsIStreamListener) ||
    > > * * * * * * * * * * *iid.equals
    > > (Components.interfaces.nsIMsgHeaderSink) ||
    > > * * * * * * * * * * * * iid.equals(Components.interfaces.nsISupports))
    > > {
    > > * * * * * * * * * * return this;
    > > * * * * * * * * } else {
    > > * * * * * * * * * * throw Components.results.NS_NOINTERFACE;
    > > * * * * * * * * * * return 0;
    > > * * * * * * * * }
    > > * * * * * * },

    >
    > > * * * * * * onStartRequest : function (aRequest, aContext) {
    > > * * * * * * },

    >
    > > * * * * * * onStopRequest : function (aRequest, aContext, aStatusCode)
    > > {
    > > * * * * * * * * this._finaldata = this._data;
    > > * * * * * * },

    >
    > > * * * * * * onDataAvailable : function (aRequest, aContext,
    > > aInputStream, aOffset, aCount) {
    > > * * * * * * * * var binInputStream = Components.classes["@mozilla.org/
    > > binaryinputstream;1"].createInstance
    > > (Components.interfaces.nsIBinaryInputStream);
    > > * * * * * * * * binInputStream.setInputStream(aInputStream);
    > > * * * * * * * * if (this._first) {
    > > * * * * * * * * * * * this._data = binInputStream.readBytes
    > > (binInputStream.available());
    > > * * * * * * * * * * * this._first = false;
    > > * * * * * * * * } else{
    > > * * * * * * * * * this._data += binInputStream.readBytes
    > > (binInputStream.available());
    > > * * * * * * * * * *binInputStream.close();
    > > * * * * * * * *}
    > > * * * * * * },
    > > * * * * };
    > > * * * * return aListener;

    >
    > > }

    >
    > > The code from the dialog:

    >
    > > custombutton_accept = function(){
    > > * msg_stream = window.arguments[0].inn.msg_stream;
    > > * var lade = window.setInterval("wait_until_finished(msg_stream)",
    > > 500);

    >
    > > * function wait_until_finished(stream){
    > > * * if(stream._finaldata){
    > > * * *log(stream._finaldata);
    > > * * *window.clearInterval(lade);
    > > * * *get_body(stream._finaldata);
    > > * * }
    > > * };

    >
    > > * function get_body(body){
    > > * *alert(body);
    > > * *return true;
    > > * };

    >
    > > * return true;

    >
    > > }

    >
    > > Since I want to check every x ms I tried using setInterval, however
    > > the dialog simply gets closed as the code isn't stopped after
    > > setInterval, instead it simply continues and closes the dialog. I
    > > waited a bit to see if afterwards something happened but there never
    > > came anything.

    >
    > > I also tried setTimeout:

    >
    > > custombutton_accept = function(){
    > > * msg_stream = window.arguments[0].inn.msg_stream;
    > > * wait_until_finished(msg_stream);

    >
    > > }

    >
    > > wait_until_finished = function(stream){
    > > * if(stream._finaldata){
    > > * * log(stream._finaldata);
    > > * * get_body(stream._finaldata);
    > > * }else{
    > > * * window.setTimeout("wait_until_finished(stream)",500);
    > > * }

    >
    > > }

    >
    > > get_body = function(body){
    > > * /*do something*/
    > > * alert(body);

    >
    > > }

    >
    > > Same problem as with setInterval.

    >
    > > A combination of while and setInterval:

    >
    > > wait_until_finished = function(stream){
    > > * *while( !stream._finaldata() ){
    > > * * * *setTimeout('wait_until_finished(stream)', 100)
    > > * *}
    > > * *get_body(stream._finaldata());}

    >
    > > This froze the ui as if you just used while, since the code doesn't
    > > stop after setInterval.

    >
    > > I don't know what else to try. Any tipps/hints/code examples are
    > > greatly appreciated.

    >
    > > Greetings,
    > > Serratia

    >
    > I think it's best to use the event queue service object instead of
    > setting timeouts which pretty much stalls the entire UI thread while
    > still being mixed in with current browser thread: @mozilla.org/event-
    > queue-service
    >
    > ----------------------------------8<----------------------------------
    > Components.classes["@mozilla.org/event-queue-service;1"].getService
    > (Components.interfaces.nsIEventQueueService)
    > ---------------------------------->8----------------------------------
    >
    > And use an asynchrounous request to resolve it, but you'll have to
    > embed the listener in the object while resolving it so that it can
    > notify the listener when data is available, or stopped. Like:
    > onDataAvailable.
    >
    > Please correct me if I'm wrong or don't understand your question
    > properly.
    >
    > /rvdh


    nsIEventQueueServide doesn't seem to exist in the current versions.
    According to http://markmail.org/message/2p63wgqhzwtpujiy it has been
    replaced by nsIThreadManager, which I knew about but in through
    http://groups.google.com/group/mozil...79dec301a06d2f
    I got discouraged in reading in further.

    Greetings,
    Serratia

  4. Re: getting result of async streamMessage

    On 24 Mrz., 10:46, Neil wrote:
    > Red_Serra...@hotmail.de wrote:
    > >custombutton_accept = function(){
    > > *msg_stream = window.arguments[0].inn.msg_stream;
    > > *wait_until_finished(msg_stream);
    > >}

    >
    > A dialog's accept button will close the dialog unless you return false here.
    >
    > Rather than using a timeout, you might consider adding an extra callback
    > property to the stream something like this:
    >
    > onStopRequest : function (aRequest, aContext, aStatusCode) {
    > * * this._finalData = this._data;
    > * * if (this._callback)
    > * * * *this._callback(this._finalData);
    >
    > },
    >
    > custombutton_accept = function() {
    > * * function get_body(body) {
    > * * * *alert(body);
    > * * * *window.close();
    > * * }
    > * * var msg_stream = window.arguments[0].inn.msg_stream;
    > * * if (msg_stream._finalData)
    > * * * *get_body(msg_stream._finalData);
    > * * else
    > * * * * msg_stream._callback = get_body;
    > * * return false;
    >
    > }
    >
    > Not shown: code to cancel the callback when the dialog is cancelled;
    > code to deal with clicking OK twice; etc.
    >
    > --
    > Warning: May contain traces of nuts.


    This worked excellent, so thank you very much. =) This is quite a
    beautiful solution.

    Greetings,
    Serratia

+ Reply to Thread