Ошибка CORS при переходе из jQuery в ваниль [дубликат]

На серверах Linux / Unix вы можете выполнить задание в фоновом режиме с помощью proc_open :

  $ descriptorspec = array (array ('pipe', '  r '), // stdin array (' file ',' myfile.txt ',' a '), // stdout array (' pipe ',' w '), // stderr);  $ proc = proc_open ('php email_script.php & amp;', $ descriptorspec, $ pipes);   

Здесь важный бит здесь & amp; . Сценарий будет продолжен, даже если исходный скрипт закончился.

111
задан informatik01 26 October 2013 в 01:31
поделиться

11 ответов

/**
 * Get JSONP data for cross-domain AJAX requests
 * @private
 * @link http://cameronspear.com/blog/exactly-what-is-jsonp/
 * @param  {String} url      The URL of the JSON request
 * @param  {String} callback The name of the callback to run on load
 */
var loadJSONP = function ( url, callback ) {

    // Create script with url and callback (if specified)
    var ref = window.document.getElementsByTagName( 'script' )[ 0 ];
    var script = window.document.createElement( 'script' );
    script.src = url + (url.indexOf( '?' ) + 1 ? '&' : '?') + 'callback=' + callback;

    // Insert script tag into the DOM (append to <head>)
    ref.parentNode.insertBefore( script, ref );

    // After the script is loaded (and executed), remove it
    script.onload = function () {
        this.remove();
    };

};

/** 
 * Example
 */

// Function to run on success
var logAPI = function ( data ) {
    console.log( data );
}

// Run request
loadJSONP( 'http://api.petfinder.com/shelter.getPets?format=json&key=12345&shelter=AA11', 'logAPI' );
0
ответ дан 2pha 15 August 2018 в 21:41
поделиться
  • 1
    Почему window.document.getElementsByTagName('script')[0];, а не document.body.appendChild(…)? – Sukima 4 August 2016 в 16:10
  • 2
    Должно ли logAPI быть установлено на null, когда это сделано, чтобы на нем могла быть выполнена сборка мусора? – Sukima 4 August 2016 в 16:11

Что такое JSONP?

Важная вещь, которую нужно запомнить с помощью jsonp, заключается в том, что на самом деле это не протокол или тип данных. Его просто способ загрузки скрипта «на лету» и обработки скрипта, который вводится на страницу. В духе JSONP это означает введение нового javascript-объекта с сервера в клиентское приложение / скрипт.

Когда нужен JSONP?

Это один способ разрешить один домен для доступа / обработки данных от другого на одной странице асинхронно. Прежде всего, он используется для переопределения ограничений CORS (Cross Origin Resource Sharing), которые могут возникнуть с запросом XHR (ajax).

Как это делается

Представление нового объекта JavaScript с сервера может быть реализовано по-разному, но наиболее распространенная практика заключается в том, что сервер для реализации выполнения функции обратного вызова с требуемым объектом, переданным в него. Функция обратного вызова - это только функция, которую вы уже настроили на клиенте, который сценарий загружает вызовы в точке , загружаемые скриптом для обработки переданных ему данных.

Пример:

У меня есть приложение, которое регистрирует все предметы в чьем-то доме. Мое приложение настроено, и теперь я хочу получить все предметы в главной спальне.

Мое приложение находится на app.home.com. Мне нужно загрузить данные apis из api.home.com.

Если сервер явно не установлен для его разрешения, я не могу использовать ajax для загрузки этих данных, так как даже страницы на отдельных субдоменах подвержены ограничениям XHR CORS.

В идеале, установите вещи, позволяющие X-домен XHR

В идеале, поскольку api и app находятся в одном домене, у меня может быть доступ к настройке заголовков на api.home.com. Если да, я могу добавить элемент заголовка Access-Control-Allow-Origin:, предоставляющий доступ к app.home.com. Предполагая, что заголовок настроен следующим образом: Access-Control-Allow-Origin: "http://app.home.com", это гораздо безопаснее, чем настройка JSONP. Это связано с тем, что app.home.com может получить все, что хочет от api.home.com без api.home.com, предоставляя CORS доступ ко всему интернету.

Вышеупомянутое решение XHR невозможно. Настройка JSONP На моем клиентском скрипте: я настроил функцию для обработки ответа с сервера, когда я делаю вызов JSONP. :

function processJSONPResponse(data) {
    var dataFromServer = data;
}

Серверу необходимо будет чтобы вернуть мини-скрипт, выглядящий как "processJSONPResponse({"room":"main bedroom","items":["bed","chest of drawers"]});". Он может быть сконструирован так, чтобы возвращать такую ​​строку, если вызывается что-то вроде //api.home.com?getdata=room&room=main_bedroom.

Затем клиент устанавливает тег сценария как таковой:

var script = document.createElement('script');
script.src = '//api.home.com?getdata=room&room=main_bedroom';

document.querySelector('head').appendChild(script);

Загружает скрипт и сразу вызывает window.processJSONPResponse() как написанный / эхо / распечатанный сервером. Данные, переданные в качестве параметра функции, теперь сохраняются в локальной переменной dataFromServer, и вы можете делать с ней все, что вам нужно.

Очистить

После того, как клиент данные, т.е. сразу после добавления сценария в DOM, элемент сценария может быть удален из DOM:

script.parentNode.removeChild(script);
24
ответ дан dewd 15 August 2018 в 21:41
поделиться
  • 1
    Большое спасибо, это очень помогло моему проекту. Небольшая проблема: я получил SyntaxError: JSON.parse: unexpected character at line 1 column 2 of the JSON data. После добавления одинарных кавычек к данным все работало нормально, поэтому: "processJSONPResponse('{"room":"main bedroom","items":["bed","chest of drawers"]}');" – Hein van Dyke 8 June 2017 в 15:51

Я написал библиотеку, чтобы справиться с этим, как можно проще. Нет необходимости делать его внешним, его только одна функция. В отличие от некоторых других параметров, этот скрипт очищается после себя и обобщается для получения дополнительных запросов во время выполнения.

https://github.com/Fresheyeball/micro-jsonp

function jsonp(url, key, callback) {

    var appendParam = function(url, key, param){
            return url
                + (url.indexOf("?") > 0 ? "&" : "?")
                + key + "=" + param;
        },

        createScript = function(url, callback){
            var doc = document,
                head = doc.head,
                script = doc.createElement("script");

            script
            .setAttribute("src", url);

            head
            .appendChild(script);

            callback(function(){
                setTimeout(function(){
                    head
                    .removeChild(script);
                }, 0);
            });
        },

        q =
            "q" + Math.round(Math.random() * Date.now());

    createScript(
        appendParam(url, key, q), function(remove){
            window[q] =
                function(json){
                    window[q] = undefined;
                    remove();
                    callback(json);
                };
        });
}
2
ответ дан Fresheyeball 15 August 2018 в 21:41
поделиться
/**
 * Loads data asynchronously via JSONP.
 */
const load = (() => {
  let index = 0;
  const timeout = 5000;

  return url => new Promise((resolve, reject) => {
    const callback = '__callback' + index++;
    const timeoutID = window.setTimeout(() => {
      reject(new Error('Request timeout.'));
    }, timeout);

    window[callback] = response => {
      window.clearTimeout(timeoutID);
      resolve(response.data);
    };

    const script = document.createElement('script');
    script.type = 'text/javascript';
    script.async = true;
    script.src = url + (url.indexOf('?') === -1 ? '?' : '&') + 'callback=' + callback;
    document.getElementsByTagName('head')[0].appendChild(script);
  });
})();

Пример использования:

const data = await load('http://api.github.com/orgs/kriasoft');
5
ответ дан Konstantin Tarkus 15 August 2018 в 21:41
поделиться
  • 1
    Не забудьте window[callback] = null, чтобы функция сбора мусора. – Sukima 4 August 2016 в 16:00
function foo(data)
{
    // do stuff with JSON
}

var script = document.createElement('script');
script.src = '//example.com/path/to/jsonp?callback=foo'

document.getElementsByTagName('head')[0].appendChild(script);
// or document.head.appendChild(script) in modern browsers
145
ответ дан Matt Ball 15 August 2018 в 21:41
поделиться
  • 1
    Вот JSBin, который можно использовать для скрипта с JSONP из Википедии. На этот ответ в был дан ответ . – rkagerer 8 March 2013 в 16:07
  • 2
    Я думаю, стоит отметить, что ответ должен иметь форму: foo(payload_of_json_data), идея состоит в том, что когда он загружается в тег скрипта, он вызывает функцию foo с полезной нагрузкой уже как объект javascript, и никакой синтаксический анализ не нужен , – Octopus 19 September 2014 в 04:32
  • 3
    Это работает, но что, если вам нужно добавить заголовки? – Will Munn 14 August 2016 в 10:17
  • 4
    @WillMunn Я не думаю, что это возможно с JSONP. Это взлом от дней до CORS. Для чего нужны заголовки? Серверу необходимо принимать JSONP-запросы, поэтому он должен быть настроен для правильного использования. – Matt Ball 14 August 2016 в 21:54
  • 5
    вы правы, я неправильно прочитал документацию api, есть специальный параметр запроса, чтобы делать то, что я хотел, используя jsonp-приложения. – Will Munn 15 August 2016 в 06:53

Ниже приведен пример JavaScript для вызова JSONP без JQuery:

Кроме того, вы можете ссылаться на мой репозиторий GitHub для ссылки.

https://github.com/shedagemayur/JavaScriptCode/tree/master/jsonp

window.onload = function(){
    var callbackMethod = 'callback_' + new Date().getTime();

    var script = document.createElement('script');
    script.src = 'https://jsonplaceholder.typicode.com/users/1?callback='+callbackMethod;

    document.body.appendChild(script);

    window[callbackMethod] = function(data){
        delete window[callbackMethod];
        document.body.removeChild(script);
        console.log(data);
    }
}

0
ответ дан Mayur Shedage 15 August 2018 в 21:41
поделиться

Если вы используете ES6 с NPM, вы можете попробовать модуль узла «fetch-jsonp». Fetch API Предоставляет поддержку для вызова JsonP как обычного XHR-вызова.

Предварительное условие: вы должны использовать модуль узла isomorphic-fetch в вашем стеке.

0
ответ дан Rajendra kumar Vankadari 15 August 2018 в 21:41
поделиться

У меня есть чистая библиотека javascript, чтобы сделать это https://github.com/robertodecurnex/J50Npi/blob/master/J50Npi.js

Взгляните на него и дайте мне знать, нужна ли вам какая-либо помощь при использовании или понимании кода.

Кстати, у вас есть простой пример использования здесь: http://robertodecurnex.github.com/J50Npi/

6
ответ дан robertodecurnex 15 August 2018 в 21:41
поделиться

Я понимаю, что вы на самом деле используете теги сценариев с JSONP, sooo ...

Первым шагом является создание вашей функции, которая будет обрабатывать JSON:

function hooray(json) {
    // dealin wit teh jsonz
}

Убедитесь, что эта функция доступна на глобальном уровне.

Затем добавьте элемент сценария в DOM:

var script = document.createElement('script');
script.src = 'http://domain.com/?function=hooray';
document.body.appendChild(script);

Скрипт загрузит JavaScript, который создает поставщик API , и выполнить его.

17
ответ дан sdleihssirhc 15 August 2018 в 21:41
поделиться
  • 1
    Всем спасибо. Получил, что он стреляет по Интернету в поисках некоторых данных, а затем я что-то делаю с ним. Я использовал eval () для данных ответа, которые помогли мне разобраться с массивом объектов, который он (я думаю). {Это был медведь, вычисляющий разбор с моей ограниченной мозговой мощью, но я, наконец, получил значение, извлеченное из него}. Фантастика. – Dave 26 May 2011 в 05:30
  • 2
    @Dave @Matt Может быть, я am нечеткий на JSONP, но вам не нужны eval или parse или что-то еще. Вы должны получить JavaScript, который браузер может просто выполнить, не так ли? – sdleihssirhc 26 May 2011 в 20:15
  • 3
    Мой плохой, извините за путаницу. Попытка получить вещь (значение? Property?) Из массива делала мой поворот головы (вложенность, обратный вызов, массив, элемент, объект, строка, значение, фигурные скобки, скобки ...). Я удалил использование eval и все еще получил свойство (значение?) Из массива (object? Element?), Который я хотел. – Dave 29 May 2011 в 06:14

Пример с легким весом (с поддержкой onSuccess и onTimeout). Вам нужно передать имя обратного вызова в URL, если вам это нужно.

var $jsonp = (function(){
  var that = {};

  that.send = function(src, options) {
    var callback_name = options.callbackName || 'callback',
      on_success = options.onSuccess || function(){},
      on_timeout = options.onTimeout || function(){},
      timeout = options.timeout || 10; // sec

    var timeout_trigger = window.setTimeout(function(){
      window[callback_name] = function(){};
      on_timeout();
    }, timeout * 1000);

    window[callback_name] = function(data){
      window.clearTimeout(timeout_trigger);
      on_success(data);
    }

    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.async = true;
    script.src = src;

    document.getElementsByTagName('head')[0].appendChild(script);
  }

  return that;
})();

Использование примера:

$jsonp.send('some_url?callback=handleStuff', {
    callbackName: 'handleStuff',
    onSuccess: function(json){
        console.log('success!', json);
    },
    onTimeout: function(){
        console.log('timeout!');
    },
    timeout: 5
});

В GitHub: https://github.com/ sobstel / jsonp.js / блоб / ведущий / jsonp.js

33
ответ дан sobstel 15 August 2018 в 21:41
поделиться

, как я использую jsonp, как показано ниже:

function jsonp(uri) {
    return new Promise(function(resolve, reject) {
        var id = '_' + Math.round(10000 * Math.random());
        var callbackName = 'jsonp_callback_' + id;
        window[callbackName] = function(data) {
            delete window[callbackName];
            var ele = document.getElementById(id);
            ele.parentNode.removeChild(ele);
            resolve(data);
        }

        var src = uri + '&callback=' + callbackName;
        var script = document.createElement('script');
        script.src = src;
        script.id = id;
        script.addEventListener('error', reject);
        (document.getElementsByTagName('head')[0] || document.body || document.documentElement).appendChild(script)
    });
}

, затем используйте метод «jsonp» следующим образом:

jsonp('http://xxx/cors').then(function(data){
    console.log(data);
});

ссылка:

JavaScript XMLHttpRequest с использованием JsonP

http://www.w3ctech.com/topic/721 (расскажите о способе использования Promise)

7
ответ дан Zach Saucier 15 August 2018 в 21:41
поделиться
  • 1
    прекратить назначение script.src = src; добавить ';' до конца всех заданий – chdev77 14 June 2017 в 18:40
Другие вопросы по тегам:

Похожие вопросы: