Используйте функцию reviver в запросах jQuery.ajax - PullRequest
0 голосов
/ 10 января 2019

У меня есть ответы AJAX, где указаны все пары key,value. Я хочу удалить кавычки из любых значений, которые являются числами. Мне нужно сделать это глобально, для всех запросов AJAX, с минимальными усилиями.

Я использую jQuery.getJSON для большинства запросов, и мне нужно решение, которое не требует индивидуальной настройки каждого из текущих запросов AJAX. (Я не хочу добавлять JSON.parse(text,myreviver) вызов в каждый из существующих $.getJSON вызовов.)

Например:

Received:    {"age":"31", "money": "-1.329"}
Want:        {"age": 31, "money": -1.329}

Как я могу это сделать, для всех запросов AJAX ?

Моя текущая конечная цель - использовать JSON.parse(text, reviver) для обработки данных (благодаря этот вопрос ). Я не знаю, как подключить это к jQuery.ajax, хотя.

Я пытался использовать ajaxSuccess(), но, похоже, он не обрабатывает данные по цепочке. Например:

$(document.ajaxSuccess) ( function(j) {
    JSON.parse(j, myReviver);
}

.getJSON(url, data, function(j) {
    // The data in this success function has not been through myReviver.
}

Как я могу:

  • использовать функцию оживления в jQuery.getJSON или
  • обработать ответ AJAX в глобальной success функции до того, как достигнет других функций успеха?

Ответы [ 2 ]

0 голосов
/ 10 января 2019

Вы можете переопределить текст по умолчанию для преобразования в json, используя ajaxSetup "глобально, для всех запросов AJAX, с минимальными усилиями."

$.ajaxSetup({
  converters: {
    // default was jQuery.parseJSON
    'text json': data => JSON.parse(data, numberReviver)
  }
})


$.getJSON('https://jsonplaceholder.typicode.com/users')
  .then(users => users.map(user => ({email: user.email, geo: user.address.geo})))
  .then(console.log)
  
function numberReviver(name, value) {
  if(typeof value === 'string' && /^[+-]?[0-9]+(?:\.[0-9]+)$/.test(value)) {
    console.log(`Using custom reviver for ${name}:${value}`)
    value = Number(value)
  }
  
  return value
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
0 голосов
/ 10 января 2019

Вы можете перезаписать .getJSON собственным методом.

Родной getJSON метод можно увидеть здесь:

https://j11y.io/jquery/#v=git&fn=jQuery.getJSON

function (url, data, callback) {
  return jQuery.get(url, data, callback, "json");
}

Достаточно просто принять ответный вызов, переданный на getJSON, передать свой собственный обратный вызов на jQuery.get с 'text' вместо 'json', проанализировать JSON с помощью пользовательского reviver, и затем вызовите исходный обратный вызов.

Сложность заключается в том, что второй параметр, переданный в getJSON, является необязательным (данные для отправки вместе с запросом).

Предполагая, что вы всегда используете функцию успеха (третий и последний аргумент), вы можете использовать остальные параметры и pop(), чтобы получить переданную функцию успеха. Создайте пользовательскую функцию успеха, которая принимает текстовый ответ и использует пользовательский JSON.parse, а затем вызывает переданную функцию успеха с созданным объектом.

const dequoteDigits = json => JSON.parse(
  json,
  (key, val) => (
    typeof val === 'string' && /^[+-]?[0-9]+(?:\.[0-9]+)$/.test(val)
    ? Number(val)
    : val
  )
);
jQuery.getJSON = function (url, ...rest) {
  // normal parameters: url, data (optional), success
  const success = rest.pop();
  const customSuccess = function(textResponse, status, jqXHR) {
    const obj = dequoteDigits(textResponse);
    success.call(this, obj, status, jqXHR);
  };
  // spread the possibly-empty empty array "rest" to put "data" into argument list
  return jQuery.get(url, ...rest, customSuccess, 'text');
};

jQuery.getJSON('https://jsonplaceholder.typicode.com/users', (obj) => {
  console.log(obj);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Разница в выводе фрагмента выше по сравнению с запрошенным URL

https://jsonplaceholder.typicode.com/users

означает, что значения свойств широты и долготы были преобразованы в числа, а не в оставшиеся строки.

Если вы когда-либо используете await также без обратного вызова, то вам нужно перезаписать свойство then возвращенного Promise, хотя работа с необязательным обратным вызовом успеха делает логику кода намного более уродливой:

const dequoteDigits = json => JSON.parse(
  json,
  (key, val) => (
    typeof val === 'string' && /^[+-]?[0-9]+(?:\.[0-9]+)$/.test(val)
    ? Number(val)
    : val
  )
);
jQuery.getJSON = function (url, ...rest) {
  // normal parameters: url, data (optional), success (optional)
  const data = rest.length && typeof rest[0] !== 'function'
  ? [rest.shift()]
  : [];
  
  const newSuccessArr = typeof rest[0] === 'function'
  ? [function(textResponse, status, jqXHR) {
        const obj = dequoteDigits(textResponse);
        rest[0].call(this, obj, status, jqXHR);
      }
    ]
  : [];
  // spread the possibly-empty dataObj and newSuccessObj into the new argument list array
  const newArgs = [url, ...data, ...newSuccessArr, 'text'];
  
  const prom = jQuery.get.apply(this, newArgs);
  const nativeThen = prom.then;
  prom.then = function(resolve) {
    nativeThen.call(this)
      .then((res) => {
        const obj = dequoteDigits(this.responseText);
        resolve(obj);
      });
  };
  return prom;
};


jQuery.getJSON('https://jsonplaceholder.typicode.com/users', (obj) => {
  console.log(obj[0].address.geo);
});



(async () => {
  const obj = await jQuery.getJSON('https://jsonplaceholder.typicode.com/users');
  console.log(obj[0].address.geo);
  // console.log(obj);
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...