Skip to main content
added 1134 characters in body
Source Link
Philip
  • 182
  • 1
  • 4

[UPDATE]:

I have used arrow functions to write cleaner and shorter code. You can see it for example at the end of the ajax function (ontimeout and onerror)

before:

  xhr.ontimeout = function(e) {
    console.error(e);
    cb(false);
  };

after:

  xhr.ontimeout = e => reject(e);

Also i've used the spread operator to extend the opts variable. Info: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Operators/Spread_operator

ajax, xhr and opts changed from var to const, because theire values never change.

The ajax function now returns a Promise instead of calling a function. Better error handling, chaining and state of the art.

I've removed all console.log calls and always return an Error Object for better handling instead of false.


const ajax = (options) => {
  const xhr = new XMLHttpRequest();

  // request options
  const opts = {
    withCredentials: false,
    method: options.method || 'GET',
    ...options
  };

  xhr.withCredentials = options.withCredentials;
  xhr.open(opts.method, opts.url);
  xhr.setRequestHeader('Accept', opts.type || 'text/plain');
  xhr.send(opts.body || null);

  // create promise to handle asynchron call
  return new Promise((resolve, reject) => {
    xhr.onreadystatechange = () => {
      if (xhr.readyState === XMLHttpRequest.DONE) {
        if (xhr.status >= 200 && xhr.status < 300) {
          resolve(xhr.responseText);
        } else {
          // return errors if status is wrong (catch)
          reject(new Error(xhr.status));
        }
      }
    } 

    // return errors on timeout (catch)
    xhr.ontimeout = e => reject(e);
    xhr.onerror = e => reject(e);
  })
} 


ajax({
  url: '/echo/json',
  method: 'POST', // Standard: GET
  type: 'application/json', // Standard: text/plain
  body: {  // Standard: null
    form: 'data'
  }
}).then(data => data)
  // chaining. Handle returned `data` in next `then`
  .then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

const ajax = (options) => {
  const xhr = new XMLHttpRequest();

  const opts = {
    withCredentials: false,
    method: options.method || 'GET',
    ...options
  };

  xhr.withCredentials = options.withCredentials;
  xhr.open(opts.method, opts.url);
  xhr.setRequestHeader('Accept', opts.type || 'text/plain');
  xhr.send(opts.body || null);

  return new Promise((resolve, reject) => {
    xhr.onreadystatechange = () => {
      if (xhr.readyState === XMLHttpRequest.DONE) {
        if (xhr.status >= 200 && xhr.status < 300) {
          resolve(xhr.responseText);
        } else {
          reject(new Error(xhr.status));
        }
      }
    }

    xhr.ontimeout = e => reject(e);
    xhr.onerror = e => reject(e);
  })
}

ajax({
  url: '/echo/json',
  method: 'POST', // Standard: GET
  type: 'application/json', // Standard: text/plain
  body: {  // Standard: null
    form: 'data'
  }
}).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});

[UPDATE]:

I have used arrow functions to write cleaner and shorter code. You can see it for example at the end of the ajax function (ontimeout and onerror)

before:

  xhr.ontimeout = function(e) {
    console.error(e);
    cb(false);
  };

after:

  xhr.ontimeout = e => reject(e);

Also i've used the spread operator to extend the opts variable. Info: https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Operators/Spread_operator

ajax, xhr and opts changed from var to const, because theire values never change.

The ajax function now returns a Promise instead of calling a function. Better error handling, chaining and state of the art.

I've removed all console.log calls and always return an Error Object for better handling instead of false.


const ajax = (options) => {
  const xhr = new XMLHttpRequest();

  // request options
  const opts = {
    withCredentials: false,
    method: options.method || 'GET',
    ...options
  };

  xhr.withCredentials = options.withCredentials;
  xhr.open(opts.method, opts.url);
  xhr.setRequestHeader('Accept', opts.type || 'text/plain');
  xhr.send(opts.body || null);

  // create promise to handle asynchron call
  return new Promise((resolve, reject) => {
    xhr.onreadystatechange = () => {
      if (xhr.readyState === XMLHttpRequest.DONE) {
        if (xhr.status >= 200 && xhr.status < 300) {
          resolve(xhr.responseText);
        } else {
          // return errors if status is wrong (catch)
          reject(new Error(xhr.status));
        }
      }
    } 

    // return errors on timeout (catch)
    xhr.ontimeout = e => reject(e);
    xhr.onerror = e => reject(e);
  })
} 


ajax({
  url: '/echo/json',
  method: 'POST', // Standard: GET
  type: 'application/json', // Standard: text/plain
  body: {  // Standard: null
    form: 'data'
  }
}).then(data => data)
  // chaining. Handle returned `data` in next `then`
  .then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});
Source Link
Philip
  • 182
  • 1
  • 4

I updated your code a little bit. Have a nice day ;)

const ajax = (options) => {
  const xhr = new XMLHttpRequest();

  const opts = {
    withCredentials: false,
    method: options.method || 'GET',
    ...options
  };

  xhr.withCredentials = options.withCredentials;
  xhr.open(opts.method, opts.url);
  xhr.setRequestHeader('Accept', opts.type || 'text/plain');
  xhr.send(opts.body || null);

  return new Promise((resolve, reject) => {
    xhr.onreadystatechange = () => {
      if (xhr.readyState === XMLHttpRequest.DONE) {
        if (xhr.status >= 200 && xhr.status < 300) {
          resolve(xhr.responseText);
        } else {
          reject(new Error(xhr.status));
        }
      }
    }

    xhr.ontimeout = e => reject(e);
    xhr.onerror = e => reject(e);
  })
}

ajax({
  url: '/echo/json',
  method: 'POST', // Standard: GET
  type: 'application/json', // Standard: text/plain
  body: {  // Standard: null
    form: 'data'
  }
}).then((data) => {
  console.log(data);
}).catch((error) => {
  console.log(error);
});