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

Example how to make simple spinner for AJAX request ? #192

Closed
riston opened this issue Aug 11, 2014 · 8 comments
Closed

Example how to make simple spinner for AJAX request ? #192

riston opened this issue Aug 11, 2014 · 8 comments
Labels
Type: Question For issues that are purely questions about Mithril, not necessarily bug reports or suggestions

Comments

@riston
Copy link

riston commented Aug 11, 2014

The basic solution what I would use is based on promises 'resolve' and 'reject'. Also one boolean flag variable needs to be used to mark the state. The possible case which is not handled is the timeout, if the server gives no timeout in some meaningful time then there should be client side timer for that.

Is there any better ways to implement the basic spinner ?

@lhorie
Copy link
Member

lhorie commented Aug 11, 2014

You could have a helper that returns both data and the flag, and use config to specify a timeout handler

var requestWithFeedback = function(args) {
  var completed = m.prop(false)
  var complete = function() {
    completed(true)
  }
  args.background = true
  args.config = function(xhr) {
    xhr.timeout = 4000
    xhr.ontimeout = function() {
      complete()
      m.redraw()
    }
  }
  return {
    data: m.request(args).then(complete, complete).then(m.redraw),
    ready: completed
  }
}

var MyController = function() {
  this.things = requestWithFeedback({method: "GET", url: "/things"})
}
var myView = function(ctrl) {
  return !ctrl.things.ready() ? m("img[src=loading.gif]") : m("ul", [
    ctrl.things.data().map(function(thing) {
      return m("li", thing.name)
    })
  ]) 
}

m.module(document.body, {controller: MyController, view: myView})

@eddyystop
Copy link

I may be missing something here, but wouldn't .then(complete, complete) always convert the payload to true as m.prop returns the stored value?

function complete () { completed.bind(this, true)(); /* or completed(true) */ } would work though.

@lhorie
Copy link
Member

lhorie commented Aug 14, 2014

@eddyystop oh you're right. My mistake. I'll fix the snippet

@eddyystop
Copy link

It's an elegant pattern. Thanks!

@mjiricka
Copy link

mjiricka commented Jun 17, 2016

To make it work, I had to do this (cosmetic changes are not important):

m.requestFeedback = function (args) {
    var completed = m.prop(false);
    var complete = function(data) {
        completed(true);
        m.redraw();

        return data;
    };

    args.background = true;
    args.config = function(xhr) {
        xhr.timeout = 4000;
        xhr.ontimeout = function() {
            complete();
            m.redraw();
        };
    };

    return {
        data: m.request(args).then(complete, complete),
        ready: completed
    };
}

I do not know how the previous example could work, unless m.redraw would return its parameter in some older version.

Usage is following:

var req = m.requestFeedback({method: 'POST', url: '/service/', data: Controller.vm});
req.data.then(status => {
   console.log(status);
});

@dead-claudia
Copy link
Member

dead-claudia commented Jun 18, 2016

@mjiricka I think Leo just made a mistake in his snippet. The proper fix would be this:

m.requestFeedback = function(args) {
  var completed = m.prop(false)
  args.background = true
  args.config = function(xhr) {
    xhr.timeout = 4000
    xhr.ontimeout = function() {
      completed(true)
      m.redraw()
    }
  }
  return {
    data: m.request(args)
      .then(
        function(data) { completed(true); return data },
        function(err) { completed(true); throw err })
      .then(function (data) { m.redraw(); return data }),
    ready: completed
  }
}

@mjiricka
Copy link

mjiricka commented Jun 18, 2016

@isiahmeadows Thank you for your quick reply! I noticed throw instead of return, that is a good idea. But is it important to call m.redraw in different promise, not immediately after setting completed(true)?

@dead-claudia
Copy link
Member

@mjiricka Not really, but you probably should at some point in the chain, if you want any changes reflected back in the view.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Question For issues that are purely questions about Mithril, not necessarily bug reports or suggestions
Projects
None yet
Development

No branches or pull requests

6 participants