0

First of all. Code of ajax_handler.php

<?php
$res = $_POST;
$res['response'] = 'Custom';
header('Content-Type: application/json');
echo json_encode($res);

I have jQuery Ajax function with Promise wrapper like this.

const _sendAjax = async (url, params = {}, dataType = 'json', method = 'POST') => new Promise(async (accept, reject) => {
    if (url.trim().length < 1)
        return reject('Invalid Url');
    method = method.trim().toUpperCase();
    if (!['POST', 'GET'].includes(method))
        return reject('Invalid Ajax Method');
    let u = new URL(url, window.location.href);
    u.searchParams.set('upd', Math.random() * 1000 + new Date().getMilliseconds());
    url = u.toString();
    $.ajax({
        url: url,
        type: method,
        processData: true,
        dataType: dataType,
        data: params,
        success: data => accept(data),
        error: (request, status, error) => {
            reject({ request, status, error });
        }
    });
});

// Callings
_sendAjax('ajax_handler.php', { a: 22, b: 23 }).then(res => console.log(res)).catch(error => console.error(error));// {"a":"22","b":"23","response":"Custom"}

_sendAjax('ajax_handler.php', { a: [1, 2, 3, 4], b: 23 }).then(res => console.log(res)).catch(error => console.error(error));// {"a":["1","2","3","4"],"b":"23","response":"Custom"}

_sendAjax('ajax_handler.php', { a: { c: [1, 2, 3, 4], d: 45 }, b: 23 }).then(res => console.log(res)).catch(error => console.error(error)); // {"a":{"c":["1","2","3","4"],"d":"45"},"b":"23","response":"Custom"}

Responses (Respectively)

console.log({"a":"22","b":"23","response":"Custom"});

console.log({"a":["1","2","3","4"],"b":"23","response":"Custom"});

console.log({"a":{"c":["1","2","3","4"],"d":"45"},"b":"23","response":"Custom"});

See, the variation in submitted data as params

I tried to convert this function to JS Fetch Api.

const _sendFetch = async (url, params = {}, dataType = 'json', method = 'POST') => new Promise(async (accept, reject) => {
    if (url.trim().length < 1)
        return reject('Invalid Url');
    method = method.trim().toUpperCase();
    if (!['POST', 'GET'].includes(method))
        return reject('Invalid Ajax Method');
    let u = new URL(url, window.location.href);
    u.searchParams.set('upd', Math.random() * 1000 + new Date().getMilliseconds());
    let fetchOptions = {
        credentials: 'include',
        cache: 'no-store',
        redirect: 'follow',
        method: method,
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
        }
    }
    if (Object.keys(params).length)
        if (method === 'POST')
            fetchOptions.body = Object.keys(params).map(x => encodeURIComponent(x) + '=' + encodeURIComponent(params[x])).join('&');
        else if (method === 'GET')
            Object.keys(params).forEach(x => u.searchParams.set(encodeURIComponent(x), encodeURIComponent(params[x])));
    url = u.toString();
    return fetch(url, fetchOptions)
        .then(res => (res.status === 200 && res.ok) ? res : reject(res))
        .then(res => dataType === 'json' ? accept(res.json()) : accept(res.text()))
        .catch(error => reject(error));
});

// Callings
_sendFetch('ajax_handler.php', { a: 22, b: 23 }).then(res => console.log(res)).catch(error => console.error(error)); // {"a":"22","b":"23","response":"Custom"}

_sendFetch('ajax_handler.php', { a: [1, 2, 3, 4], b: 23 }).then(res => console.log(res)).catch(error => console.error(error)); // {"a":"1,2,3,4","b":"23","response":"Custom"}

_sendFetch('ajax_handler.php', { a: { c: [1, 2, 3, 4], d: 45 }, b: 23 }).then(res => console.log(res)).catch(error => console.error(error)); // {"a":"[object Object]","b":"23","response":"Custom"}

Responses (Respectively)

console.log({"a":"22","b":"23","response":"Custom"});

console.log({"a":"1,2,3,4","b":"23","response":"Custom"});

console.log({"a":"[object Object]","b":"23","response":"Custom"});

Problem:

Obviously, I can't process and send inputted data as jQuery is doing because of processData: true,. jQuery seem to handle data efficiently for both POST as well as GET.

I can't to figure out a way to replicate working of processData functionality of jQuery Ajax as the params have lots of variation and I need some generic code to process inputted data for Fetch as jQuery does.

I want to do this in JS only without third party libraries like jQuery.

Umair Khan
  • 1,684
  • 18
  • 34
  • I don’t see why you are handling GET and POST separately here to begin with, when it comes to assembling your data - the format of `application/x-www-form-urlencoded` is the exact same for both to begin with, the only difference is that with GET, it gets added to the URL as query string, whereas with POST, it gets put into the body. You should probably not need much more than https://stackoverflow.com/a/54467386/1427878 here to prepare your data. – CBroe Mar 25 '20 at 10:29
  • @CBroe. The question you mentioned, 'encodeURIComponent(JSON.stringify(params))` and `new URLSearchParams(params)` does not work as per my need on complex data like `{ a: { c: [1, 2, 3, 4], d: 45 }, b: 23 }` and I can't get the desired result. Also, `new URLSearchParams({ a: { c: [1, 2, 3, 4], d: 45 }, b: 23 }).toString()` results in `a=%5Bobject+Object%5D&b=23` – Umair Khan Mar 25 '20 at 10:47
  • You probably need a recursive solution here, because `[object Object]` is what you get when you force an object into string context. – CBroe Mar 25 '20 at 10:53
  • Are you trying to completely get rid of jQuery here? Because if not, you could simply use its https://api.jquery.com/jQuery.param/ – CBroe Mar 25 '20 at 10:55
  • @CBroe, I know about `jQuery.param`, but as you have guessed, I want to do it without *jQuery*. – Umair Khan Mar 25 '20 at 10:58
  • 1
    https://github.com/knowledgecode/jquery-param has a light-weight implementation of that, that doesn’t need jQuery. Either embed it as-is, or extract the relevant logic from it. – CBroe Mar 25 '20 at 11:03
  • @CBroe. Thanks, https://github.com/knowledgecode/jquery-param seems to work for my issue. Much appreciated. – Umair Khan Mar 25 '20 at 11:22

1 Answers1

0

I did mention that I only want the solution in JS but as commented by @CBore that I have few options in this matter.

  1. Write my own recursive function.
  2. Use URLSearchParams as described here. But this is not working for my scenario as the params are not just simple object.

console.log(new URLSearchParams({ a: { c: [1, 2, 3, 4], d: 45 }, b: 23 }).toString());
  1. Use jQuery.param. But I do not want to use a full library just for a single function / advantage.
  2. Use light-weight library like jquery-param.

So in the end, I have settled for jquery-param for the time being.

Umair Khan
  • 1,684
  • 18
  • 34