На серверах 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;
. Сценарий будет продолжен, даже если исходный скрипт закончился.
/**
* 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' );
Что такое 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);
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);
};
});
}
/**
* 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');
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
foo(payload_of_json_data)
, идея состоит в том, что когда он загружается в тег скрипта, он вызывает функцию foo с полезной нагрузкой уже как объект javascript, и никакой синтаксический анализ не нужен ,
– Octopus
19 September 2014 в 04:32
Ниже приведен пример 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);
}
}
Если вы используете ES6 с NPM, вы можете попробовать модуль узла «fetch-jsonp». Fetch API Предоставляет поддержку для вызова JsonP как обычного XHR-вызова.
Предварительное условие: вы должны использовать модуль узла isomorphic-fetch
в вашем стеке.
У меня есть чистая библиотека javascript, чтобы сделать это https://github.com/robertodecurnex/J50Npi/blob/master/J50Npi.js
Взгляните на него и дайте мне знать, нужна ли вам какая-либо помощь при использовании или понимании кода.
Кстати, у вас есть простой пример использования здесь: http://robertodecurnex.github.com/J50Npi/
Я понимаю, что вы на самом деле используете теги сценариев с 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 , и выполнить его.
eval
или parse
или что-то еще. Вы должны получить JavaScript, который браузер может просто выполнить, не так ли?
– sdleihssirhc
26 May 2011 в 20:15
Пример с легким весом (с поддержкой 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
, как я использую 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)
window.document.getElementsByTagName('script')[0];
, а неdocument.body.appendChild(…)
? – Sukima 4 August 2016 в 16:10logAPI
быть установлено наnull
, когда это сделано, чтобы на нем могла быть выполнена сборка мусора? – Sukima 4 August 2016 в 16:11