Jump to content

How to catch uikit ajax errors?


bernhard
 Share

Recommended Posts

Hi,

I'm trying to send an ajax request on my new site via UIkit's built in little JavaScript framework: https://github.com/uikit/uikit-site/blob/feature/js-utils/docs/pages/javascript-utilities.md#ajax


util.ajax('/data/newsletter/', {
  responseType: 'json',
  method: 'POST',
  data: JSON.stringify({
    mail:mail,
    sms:sms,
    msg:msg,
    cmt:cmt,
  }),
})
.then(function(xhr) {
  console.log(xhr);
  if(xhr.status !== 200) {
    UIkit.modal.alert('error xyz');
  }
});

TT1Nv5S.png

The backend throws a WireException because the form is not filled correctly and that's totally fine.

try {
  $gg->subscribe();
}
catch(Throwable $th) {
  http_response_code(400);
  die($th->getMessage());
}

But I'd like to catch this error and show a message to the user. In jQuery this is easy:

$.post('status.ajax.php', {deviceId: id})
.done( function(msg) { ... } )
.fail( function(xhr, textStatus, errorThrown) {
	alert(xhr.responseText);
});

But how do I do that with the uikit framework or vanilla javascript? I've done some research and tried several try/catch variants but I always end up in the error message in the console.

This is the source of the uikit ajax function: https://github.com/uikit/uikit/blob/ea4453b1a71bfebb8ac43d81757071cfc5c7cca0/src/js/util/ajax.js#L5-L62

It seems that they have thought about "network error" and "network timeout". But how do I catch them?

Thx for your help ? 

PS I think @Tom. you are quite experienced with JS and Uikit?

  • Like 1
Link to comment
Share on other sites

1 hour ago, bernhard said:

In jQuery this is easy:

You will need to unlearn jQuery ?. There's a difference between an "error" and an "exception". I am guessing uikit is probably using fetch() internally? 

If using vanilla JS...

TL;DR

Quote

a wrapper that checks response.ok 

From the fetch() docs:

Quote

A fetch() promise only rejects when a network error is encountered (which is usually when there’s a permissions issue or similar). A fetch() promise does not reject on HTTP errors (404, etc.). Instead, a then() handler must check the Response.ok and/or Response.status properties.

To the solutions

  1. Handling Failed HTTP Responses With fetch()
  2. How to handle HTTP code 4xx responses in fetch api

 

  • Like 3
  • Thanks 1
Link to comment
Share on other sites

Seems UIKit is returning a Promise? 

I think this should work?? Got it from here

util.ajax('/data/newsletter/', {
  responseType: 'json',
  method: 'POST',
  data: JSON.stringify({
    mail:mail,
    sms:sms,
    msg:msg,
    cmt:cmt,
  }),
})
.then(function(xhr) {
  console.log(xhr);
  if(xhr.status !== 200) {
    UIkit.modal.alert('error xyz');
  }
}, function(error){
	//error goes here
});

 

Link to comment
Share on other sites

Thx @kongondo that helped a lot ?

Also thx @elabx this is what seems to work for me:

util.ajax('/data/newsletter/', {
  responseType: 'json',
  method: 'POST',
  data: JSON.stringify({
    mail:mail,
    sms:sms,
    msg:msg,
    cmt:cmt,
  }),
})
.then(function(response) {
  // show success message
}).catch(function(error) {
  UIkit.modal.alert('Es ist leider ein Fehler aufgetreten!<pre style="margin-top:5px;">'+error+'</pre>');
  util.removeClass(button, 'loading');
});

No idea how exactly I was using the catch statement before, but it somehow did not fire. Now everything seems to be fine, but I'll have to do more testing ? 

1 hour ago, kongondo said:

You will need to unlearn jQuery ?.

Probably not the best idea for a PW developer ? 

  • Like 2
Link to comment
Share on other sites

57 minutes ago, kongondo said:

Touché! ?.

Yes and no. This post is a result of removing jQuery from my project, so you are on one hand spot on. I'M using uikit for the frontend and I didn't want to include another framework when uikit already ships with lots of nice little helpers. Only things that I've added so far are custom methods for slideDown(), slideToggle() and slideUp() (https://gist.github.com/skttl/b8ea597ebf2db66a3e2a06491f7b4029)

Thx @adrian, you are always one step ahead ? This is my final (?) version:

let mail = util.$('#frm-mail').value;
let sms = util.$('#frm-sms').value;
let msg = util.$('#nl-form input[name=message]').value;
let cmt = util.$('#nl-form input[name=comment]').value;
let csrf = util.$('#tm-newsletter input[name=csrf]');

// show loading icon
util.addClass(button, 'loading');

// setup headers
let headers = {}
headers['X-Requested-With'] = 'XMLHttpRequest';
headers['X-'+util.data(csrf, 'tokenname')] = util.data(csrf, 'tokenvalue');

// send ajax
util.ajax('/data/newsletter/', {
  responseType: 'json',
  method: 'POST',
  headers,
  data: JSON.stringify({
    mail:mail,
    sms:sms,
    honey:msg+cmt,
  }),
})
.then(function() {
  // success
  RockUikit.slideUp(button.closest('form'));
  RockUikit.slideDown(util.$('#tm-newsletter .tm-success'));
}).catch(function(error) {
  UIkit.modal.alert('Es ist leider ein Fehler aufgetreten!<pre style="margin-top:5px;">'+error+'</pre>');
  util.removeClass(button, 'loading');
});

Server side:

// template
if(!$config->ajax) throw new Wire404Exception();
$gg->subscribe();

// module
public function subscribe() {
  try {
    $input = json_decode(file_get_contents('php://input'));
    if(!$input) throw new WireException("No data");
    if(!$this->wire->session->CSRF->hasValidToken()) {
      throw new WireException("CSRF failed");
    }

    $mail = $this->wire->sanitizer->text($input->mail);
    $sms = $this->wire->sanitizer->text($input->sms);
    $honey = $this->wire->sanitizer->text($input->honey);

    // honeypot
    if($honey) throw new WireException("Invalid request");

    // both empty?
    if(!$mail AND !$sms) throw new WireException("No data");

    // create page
    $p = new Page();
    $p->template = 'signup';
    $p->parent = '/data/newsletter';
    $p->title = implode(" | ", [
      date("Y-m-d H:i:s"),
      $mail,
      $sms
    ]);
    $p->json = json_encode(['mail'=>$mail, 'sms'=>$sms]);
    $p->save();
    die('success');
  }
  catch(\Throwable $th) {
    http_response_code(400);
    die($th->getMessage());
  }
}

Thx guys! Any ideas for improvement? ? 

  • Like 2
Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...