Replaced AJAX by fetch: not everything tested yet, but seems fine
[vchess.git] / client / src / utils / ajax.js
index 4573dd8..e43e909 100644 (file)
@@ -1,9 +1,6 @@
 import params from "../parameters"; //for server URL
 import { store } from "../store"; //for translations
 
-// TODO: replace by fetch API ?
-// https://www.sitepoint.com/xmlhttprequest-vs-the-fetch-api-whats-best-for-ajax-in-2019/
-
 // From JSON (encoded string values!) to "arg1=...&arg2=..."
 function toQueryString(data) {
   let data_str = "";
@@ -13,49 +10,44 @@ function toQueryString(data) {
   return data_str.slice(0, -1); //remove last "&"
 }
 
-// data, error: optional
-export function ajax(url, method, data, success, error) {
-  let xhr = new XMLHttpRequest();
-  if (data === undefined || typeof data === "function") {
-    //no data
-    error = success;
-    success = data;
-    data = {};
-  }
-  if (!success) success = () => {}; //by default, do nothing
-  if (!error)
-    error = errmsg => {
+// TODO: use this syntax https://stackoverflow.com/a/29823632 ?
+// data, success, error: optional
+export function ajax(url, method, options) {
+  const data = options.data || {};
+  // By default, do nothing on success and print errors:
+  if (!options.success)
+    options.success = () => {};
+  if (!options.error) {
+    options.error = (errmsg) => {
       alert(store.state.tr[errmsg] || errmsg);
     };
-  xhr.onreadystatechange = function() {
-    if (this.readyState == 4 && this.status == 200) {
-      let res_json = "";
-      try {
-        res_json = JSON.parse(xhr.responseText);
-      } catch (e) {
-        // Plain text (e.g. for rules retrieval) (TODO: no more plain text in current version)
-        success(xhr.responseText);
-      }
-      if (res_json) {
-        if (!res_json.errmsg && !res_json.errno) success(res_json);
-        else {
-          if (res_json.errmsg) error(res_json.errmsg);
-          else error(res_json.code + ". errno = " + res_json.errno);
-        }
-      }
-    }
-  };
-
-  if (["GET", "DELETE"].includes(method) && !!data) {
+  }
+  if (["GET", "DELETE"].includes(method) && !!data)
     // Append query params to URL
     url += "/?" + toQueryString(data);
+  const headers = {
+    "Content-Type": "application/json;charset=UTF-8",
+    "X-Requested-With": "XMLHttpRequest"
+  };
+  let fetchOptions = {
+    method: method,
+    headers: headers,
+  };
+  if (["POST", "PUT"].includes(method))
+    fetchOptions["body"] = JSON.stringify(data);
+  if (
+    !!options.credentials ||
+    (method != "GET" && !options.nocredentials)
+  ) {
+    fetchOptions["credentials"] = params.credentials;
   }
-  xhr.open(method, params.serverUrl + url, true);
-  xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
-  // Next line to allow cross-domain cookies in dev mode
-  if (params.cors) xhr.withCredentials = true;
-  if (["POST", "PUT"].includes(method)) {
-    xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
-    xhr.send(JSON.stringify(data));
-  } else xhr.send();
+  fetch(params.serverUrl + url, fetchOptions)
+  .then(res => res.json())
+  .then(json => {
+    if (!json.errmsg && !json.errno) options.success(json);
+    else {
+      if (!!json.errmsg) options.error(json.errmsg);
+      else options.error(json.code + ". errno = " + json.errno);
+    }
+  });
 }