Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HttpRequest Global Listeners #9381

Closed
giovannicandido opened this issue Mar 22, 2013 · 6 comments
Closed

HttpRequest Global Listeners #9381

giovannicandido opened this issue Mar 22, 2013 · 6 comments
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. closed-obsolete Closed as the reported issue is no longer relevant library-html P2 A bug or feature request we're likely to work on type-enhancement A request for a change that isn't a bug

Comments

@giovannicandido
Copy link

Thats not exactly a problem, but a core feature or improvement. As a web developer I want be able to listen to all request across libraries, so I can attach behavior like security permission across client and server, or simply give a nice user feedback, or trying to connect again to the server. The point here is that I can't do this using Futures, because a Future is bonded to the caller and I can't listen everything. One workaround is to build a singleton class that wraps the HttpRequest class and construct the HttpRequest, attach you own listen before returning and them forwards the events to the outside world in a static or global way. But that is not global because other libraries will not be using my class they will use the HttpRequest and the custom class will not be able to catch this events.

There is a use case:

After all request the server send a custom HttpCode that mean the user does not have rights to do that call, and than a global listen can inspect for that request and make I nice message to the user telling this and giving he a option to login as a different user, or even disabling the button that has clicked. I'm not speaking about a web page I'm speaking about a only ajax application where you can't do this in the server because all UI is running on the client and you don't have page loads (the page load only once)
Another use case is, well we need give feedback to the users, and is simple but not likely write the same code across the code using futures, well you of course put that in a separate reusable class, but you still have to call this class everywhere, with global listen you attach that once and give the proper feedback. This two concepts listeners and Futures work very well together, you can still make your request and use the response latter and the specific code bonded with the caller can still runs as well the listener at the same time.

Maybe I just don't see how to do this in the HttpRequest class or any else class.
But here is a implementation for a custom class that wraps the HttpRequest class and is working, but as I said I can do this only for my code the other libraries do not know of the existence of this class, I will call it Ajax class:

/**

  • A class for Ajax requests. This class can dispatch global events for the common [HttpRequest] events.
  • This Class is a subclass of [HttpRequest] you can use this class as usual
    /
    class Ajax implements HttpRequest {
      // The stream methods to dispatch
      static StreamController _onAbortStreamController = new StreamController.broadcast();
      static StreamController _onErrorStreamController = new StreamController.broadcast();
      static StreamController _onLoadStreamController = new StreamController.broadcast();
      static StreamController _onLoadEndStreamController = new StreamController.broadcast();
      static StreamController _onLoadStartStreamController = new StreamController.broadcast();
      static StreamController _onProgressStreamController = new StreamController.broadcast();
      /
    *
       * Return a request that always have one listen to forward globally
       * Dispatches the event for the world. All the events that this class support have to be added here
       * This method always return a new HttpRequest
       */
      factory Ajax(){
        HttpRequest request = new HttpRequest();
        request.onAbort.listen( (event) => _onAbortStreamController.add(event));
        request.onError.listen( (event) => _onErrorStreamController.add(event));
        request.onLoad.listen( (event) => _onLoadStreamController.add(event));
        request.onLoadEnd.listen( (event) => _onLoadEndStreamController.add(event));
        request.onLoadStart.listen( (event) => _onLoadStartStreamController.add(event));
        request.onProgress.listen( (event) => _onProgressStreamController.add(event));

    return request;
  }
  /**
   * Ajax return HttpRequest so, the constructor is private
   */
  Ajax._private(){

  }

  /// A global stream for onAbort
  static Stream<HttpRequestProgressEvent> get onGlobalAbort => _onAbortStreamController.stream;
  /// A global stream for onError
  static Stream<HttpRequestProgressEvent> get onGlobalError => _onErrorStreamController.stream;
  /// A global stream for handle onLoad
  static Stream<HttpRequestProgressEvent> get onGlobalLoad => _onLoadStreamController.stream;
  /// A global stream for handle onLoadEnd
  static Stream<HttpRequestProgressEvent> get onGlobalLoadEnd => _onLoadEndStreamController.stream;
  /// A global stream for handle onLoadStart
  static Stream<HttpRequestProgressEvent> get onGlobalLoadStart => _onLoadStartStreamController.stream;
  /// A global stream for handle onProgress
  static Stream<HttpRequestProgressEvent> get onGlobalProgress => _onProgressStreamController.stream;

}

A exemple of how to use this class. Lets say we have a ExceptionView class that will inspect for errors or messages from the server and make a nice popup to the user (using the Notify class):

/**
 * Classe para escuta de eventos globais e apresentacao de notificacoes genericas para o usuário.
 * Essa classe usa [Notify] e [Ajax]
 * A class for listen to global request Events and do nice user feedback. This class uses [Notify] and [Ajax]
 * Date: 19/03/13
 * Time: 18:22
 */
class ExceptionView {
  static ExceptionView _instance;
  factory ExceptionView(){
    if(_instance == null){
      _instance = new ExceptionView._private();
    }
    return _instance;
  }
  ExceptionView._private() {
     Ajax.onGlobalError.listen(_onError);
     Ajax.onGlobalLoad.listen(_onSuccess);
// HttpRequest.onErrorEvent.listen(_onError); // I can't do that
// HttpRequest.onLoadEvent.listen(_onSuccess); // I can't do that
  }
  void _onError(HttpRequestProgressEvent event){
    var target = event.target;
    if(target.response == null){
      new Notify().msg(title: 'Erro ao processar requisição', message: '''Houve um erro desconhecido ao
      processar a requisição. Código do Erro: ${t.status}''', useNotificationsApi: false);
    }else {
      new Notify().msg(title: 'Erro ao processar requisição', message: target.responseText, useNotificationsApi: false);
    }

  }
  /**
  * Display messages on the screen, if the message is not a Json message then display a error to the user.
  * If the response is a json string and have the property "message" display a message to the user. If not do nothing,
  * If the message have the property success with value false and the message property, display a error message
  * to the user with the message property
  */
  void _onSuccess(HttpRequestProgressEvent event){
    Map result;
    try {
      result = JSON.parse(event.target.responseText);
    } catch(e){
    /// If the response is not Json treat as Error, I don't use the Notifications API because the response can be a very
    /// long server response like a Http Page.
      new Notify().msg(title: 'Ocorreu um erro no servidor',message: event.target.responseText, useNotificationsApi: false,
                              stay: true );
    }
    // Only show a message if there is a message property on the response and the message isn't empty
    if(result != null && result['message'] != null){
      if(result['message'].trim() == ""){ // If message is a empty string do nothing
        return;
      }
      // Verifica se existe uma propriedade success na resposta e formata-a o titulo de acordo
      String title = result['success'] == true || result['success'] == null ? 'OK' : 'Error';
      bool stay = result['success'] == true || result['success'] == null ? false : true;
      new Notify().msg(title: title, message: result['message'], stay: stay);
    }

  }
}

I use Dart 0.4.2.8_r20259

Here is a post about this subject on google groups: https://groups.google.com/a/dartlang.org/d/topic/misc/-oQ6eYwuKdg/discussion

Sorry any wrong written but english is not my native language.

Thank you for your time.

 

@efortuna
Copy link
Contributor

Added Area-HTML, Triaged labels.

@blois
Copy link
Contributor

blois commented Apr 4, 2013

Added this to the Later milestone.
Removed Type-Defect label.
Added Type-Enhancement label.

@kevmoo
Copy link
Member

kevmoo commented Apr 7, 2014

Removed Area-HTML label.
Added Area-Library, Library-Html labels.

@kasperl
Copy link

kasperl commented Jul 10, 2014

Removed this from the Later milestone.
Added Oldschool-Milestone-Later label.

@kasperl
Copy link

kasperl commented Aug 4, 2014

Removed Oldschool-Milestone-Later label.

@giovannicandido giovannicandido added Type-Enhancement area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. library-html labels Aug 4, 2014
@kevmoo kevmoo added P2 A bug or feature request we're likely to work on type-enhancement A request for a change that isn't a bug and removed triaged labels Feb 29, 2016
@matanlurey
Copy link
Contributor

Many libraries implement these type of indirections, we don't need to in the SDK.

@matanlurey matanlurey added the closed-obsolete Closed as the reported issue is no longer relevant label Jun 22, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-core-library SDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries. closed-obsolete Closed as the reported issue is no longer relevant library-html P2 A bug or feature request we're likely to work on type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests

6 participants