Добавление нескольких параметров/аргументов в функцию обратного вызова jsonp

Как указать дополнительные аргументы для передачи функции обратного вызова jsonp?

Например, я пытаюсь получить видеоданные YouTube:

http://gdata.youtube.com/feeds/api/videos/gzDS-Kfd5XQ?v=2&alt=json-in-script&callback=youtubeFeedCallback

Функция обратного вызова javascript, которая будет вызываться, называется youtubeFeedCallback и при вызове содержит только один аргумент.

На данный момент функция будет примерно такой,

function youtubFeedCallback(response) {
...
}

То, что я хотел бы сделать, это передать второй аргумент, подобный этому,

function youtubeFeedCallback(response, divId) {
...
}

Возможно ли это сделать. Я пытался искать везде в Интернете и ничего не мог найти. Спасибо!


person Jenn    schedule 02.07.2011    source источник
comment
Вызов URL-адреса Youtube выполняется с помощью встроенного тега сценария. Я делаю несколько вызовов ввода видео, и мне нужно передать divId, чтобы я знал, какой элемент div использовать для вставки возвращаемых видеоданных json. Я бы очень хотел передать divId во время вызова URL-адреса YouTube.   -  person Jenn    schedule 02.07.2011


Ответы (3)


Вы не можете добавлять аргументы в функцию обратного вызова таким образом. Однако вы можете создать функцию-оболочку. Функция обратного вызова JSONP просто должна была быть функцией в пространстве имен по умолчанию, это означает, что вам просто нужно добавить сгенерированную функцию с известным именем в глобальный объект window. Шаг первый — придумать имя:

var callback_name = 'youtubeFeedCallback_' + Math.floor(Math.random() * 100000);

В реальном мире вы бы хотели заключить это в цикл и проверить, что window[callback_name] еще не занято; вы можете использовать window.hasOwnProperty(callback_name) для проверки. Когда у вас есть имя, вы можете создать функцию:

window[callback_name] = function(response) {
    youtubeFeedCallback(response, divId);
};

Вы бы хотели, чтобы это немного больше, хотя:

function jsonp_one_arg(real_callback, arg) {
    // Looping and name collision avoidance is left as an exercise
    // for the reader.
    var callback_name = 'jsonp_callback_' + Math.floor(Math.random() * 100000);
    window[callback_name] = function(response) {
        real_callback(response, arg);
        delete window[callback_name];  // Clean up after ourselves.
    };
    return callback_name;
}

Когда у вас есть что-то подобное, вы можете просто позвонить:

jsonp = jsonp_one_arg(youtubeFeedCallback, divId);

Затем используйте значение jsonp в качестве значения callback в URL-адресе YouTube.

Вы можете создать больше функций, подобных этой, для обработки более длинных списков аргументов. Или вы можете создать универсальную версию с arguments и apply.

person mu is too short    schedule 02.07.2011
comment
Как я могу передать второй аргумент во время вызова URL-адреса YouTube? Я помещаю URL-адрес YouTube в качестве атрибута src встроенного тега скрипта, чтобы он выполнялся при загрузке страницы и извлекал необходимые видеоданные в формате jsonc. Мне нужен второй аргумент, чтобы выяснить, в какой элемент div я буду помещать эти данные. Спасибо! - person Jenn; 02.07.2011
comment
@Jenn: Не могли бы вы использовать обработчик загрузки для установки атрибутов src? Начните страницу с http://gdata.youtube.com/... URL-адресов, скажем, в data-src атрибутах, затем ваш обработчик загрузки может передать data-src атрибуты в src атрибуты при вызове jsonp_one_arg и исправлении параметра callback перед установкой src. - person mu is too short; 02.07.2011
comment
+1: но зачем использовать случайное вместо простого создания счетчика, скажем, "jsonp_1", "jsonp_2", ...? - person 6502; 02.07.2011
comment
@ 6502: Просто чтобы вам не приходилось отслеживать, какие из них вы использовали. Вы можете использовать глобальный счетчик, если вам нужны последовательные, или вы можете перебрать window в поисках открытого слота, я полагаю. - person mu is too short; 02.07.2011
comment
@ 6502: Конечно, вы можете отслеживать порядковый номер в свойстве jsonp_one_arg.sequence_number, если вам не нужен глобальный. Но тогда вам придется ограничиться только jsonp_one_arg или использовать полноценный общий генератор обратного вызова с n-аргументами. - person mu is too short; 02.07.2011

лучший способ - указать связанный массив divId и videoId, как это

var arr = {
    'gzDS-Kfd5XQ': 'divId_1',
    'gwWS-Gasfdw': 'divId_2'
};

и в функции обратного вызова получите свой divId по videoId

function youtubFeedCallback(data)
{
    var divId = arr[data.entry.media$group.yt$videoid.$t];
}
person redexp    schedule 02.07.2011
comment
Это почти сработало бы, за исключением того, что если бы было несколько ключей массива с одним и тем же видеоидентификатором, я бы получил правильный divId. Например. Если var arr = { gfefe-eee: 'divId_1', gfefe-eee: 'divId_2' }; Мне нужно беспокоиться о том, что одни и те же видеоданные появляются в отдельных div. Спасибо хоть. - person Jenn; 03.07.2011

При создании объекта скрипта вы можете добавить к нему атрибуты и ссылаться на них позже с помощью document.currentScript. Это сработало для меня, но другим людям может понадобиться что-то более элегантное.

function blah(stuff,extraarg){
    cs=document.currentScript;
    console.log(stuff); // stuff is your json output
    console.log(cs.extraarg); // cs.extraarg is your extra arg
}

function thing(extraarg){
    var url='https://....&json_callback=blah';
    var s=document.createElement('script');
    s.src=url;
    s.extraarg=extraarg;
    document.body.appendChild(s);
}
person Tom    schedule 23.06.2020