Где хранится ответ после запроса Dojo JSONP? - PullRequest
4 голосов
/ 13 января 2012

JavaScript

Например, у меня есть следующий код JavaScript (Dojo 1.6 уже загружен):

dojo.require("dojo.io.script")

// PART I
var jsonpArgs = {
    url: "http://myapp.appspot.com/query",
    content: {
        id: "1234",
        name: "Juan",
        start_date: "2000-01-01",
        callback: "recover"
    }
};

// PART II
dojo.io.script.get(jsonpArgs).then(function(data) {
    console.log(data);
});

// PART III
function recover(data) {
    console.log(data);
}

Прямой запрос из браузера

Я понимаю, что мой сервер получит запрос, как будто я набрал в адресной строке следующее:

http://myapp.appspot.com/query?id=1234&name=Juan&start_date=2000-01-01&callback=recover

Ожидаемый ответ

Если я напрямую запросил свой сервер с помощью адресной строки браузера, я получу в формате MIME application/json и в виде открытого текста в браузере что-то вроде этого:

recover(
    {
        id: 1234,
        name: Juan,
        data: [
            ["2000-01-01", 1234],
            ["2000-01-02", 5678]
        ]
    }
);

Задача

Теперь, оглядываясь на вторую часть JavaScript, я выполнил бы запрос JSONP с dojo.io.script.get(jsonpArgs). Это возвращает Deferred объект, которым я могу воспользоваться, добавив .then после него. Обратите внимание, что я определил обработчик для события .then, который выводит на консоль data.

Однако все, что я получаю в консоли - это Event. Я попытался найти его дерево данных, но не смог найти ожидаемые данные.

Вопрос

  1. Где хранится ответ на запрос JSONP? Как мне это найти?
  2. Мой сервер (которым я управляю) только выводит текстовые данные запрошенных данных, обернутые в функцию callback (здесь указывается как recover), и задает тип application/json MIME. Есть ли что-то еще, что мне нужно настроить на моем сервере, чтобы данные ответа захватывались объектом Deferred?

Попытка решения

Я действительно могу восстановить ответ, определив функцию обратного вызова (в данном случае recover в части III JavaScript). Однако в руководствах по Dojo они просто восстанавливали данные с использованием инфраструктуры Deferred.then). Как мне это сделать с помощью Dojo Deferred s?

Обновление (на примере Twitter из учебника по Dojo)

Взять, к примеру, этот скрипт из учебника по Dojo, Получение Jiggy с JSONP . Я отредактировал его для записи данных на консоль.

dojo.require("dojo.io.script");
dojo.io.script.get({
    url: "http://search.twitter.com/search.json",
    callbackParamName: "callback",
    content: {q: "#dojo"}
}).then(function(data){
    //we're only interested in data.results, so strip it off and return it
    console.log(data); // I get an Object, not an Event, but no Twitter data when browsing the results property
    console.log(data.results) // I get an array of Objects
    return data.results;
});

Для console.log(data) я получаю Object, а не Event, как показано в моем случае. Поскольку в примере подразумевается, что данные находятся в data.results, я также пытаюсь просмотреть это дерево, но не вижу ожидаемых данных из Twitter. Я в растерянности.

Для console.log(data.results) я получаю массив Object с. Если я сделаю запрос в Twitter напрямую, это то, что я получу в виде открытого текста. Каждый Object содержит обычные метаданные твита, такие как имя пользователя, время, портрет пользователя и сам твит. Достаточно просто.

Этот бьет меня прямо по голове. Обработчик цепочки .then, анонимная функция, получает только один аргумент data. Но почему свойство results в console.log(data) и возвращаемого объекта, полученного из console.log(data.results), отличается ?

1 Ответ

6 голосов
/ 13 января 2012

Я получил его.

Реализация ручного обратного вызова

function recover(data) {
    console.log(data);
}

var jsonpArgs = {
    url: "http://myapp.appspot.com/query",
    content: {
        id: "1234",
        name: "Juan",
        start_date: "2000-01-01",
        callback: "recover"
};

dojo.io.script.get(jsonpArgs);

Это запрос, который мой сервер получит:

http://myapp.appspot.com/query?id=1234&name=Juan&start_date=2000-01-01&callback=recover

В этом случае я 'Ожидается следующий вывод от моего сервера:

recover({
    id: 1234,
    name: Juan,
    data: [
        ["2000-01-01", 1234],
        ["2000-01-02", 5678]
    ]
});

Обратите внимание на три вещи:

  1. Сервер будет ожидать callback в строке URL-адреса запроса.callback реализован как свойство jsonpArgs.
  2. Поскольку я указал callback=recover, мой сервер присоединит recover( + the_data_I_need + ), вернет всю строку в браузер,и браузер выполнит recover(the_data_I_need).Это означает ...
  3. То, что я должен определить, например, function recover(one_argument_only) {doAnythingYouWantWith(one_argument_only)}

Проблема с этим подходом состоит в том, что я не могу использовать Deferred цепочкуиспользуя .then.Например:

dojo.io.script.get(jsonpArgs).then(function(response_from_server) {
    console.log(response_from_server);
})

Это даст мне Event, без каких-либо следов ожидаемого ответа вообще.


Использование преимуществ Dojo-реализации запросов JSONP

var jsonpArgs = {
    url: "http://myapp.appspot.com/query",
    callbackParamName: "callback",
    content: {
        id: "1234",
        name: "Juan",
        start_date: "2000-01-01"
};

dojo.io.script.get(jsonpArgs);

Это запрос, который получит мой сервер:

http://myapp.appspot.com/query?id=1234&name=Juan&start_date=2000-01-01&callback=some_function_name_generated_by_dojo

В этом случае я ожидаю следующий вывод с моего сервера:

some_function_name_generated_by_dojo({
    id: 1234,
    name: Juan,
    data: [
        ["2000-01-01", 1234],
        ["2000-01-02", 5678]
    ]
});

На заметку:

  1. Обратите внимание на свойство jsonpArgs, callbackParamName.Значением этого свойства должно быть имя переменной (в строке URL-адреса запроса), ожидаемой сервером.Если мой сервер ожидает callbackfoo, то callbackParamName: "callbackfoo".В моем случае мой сервер ожидает имя callback, поэтому callbackParamName: "callback".

  2. В предыдущем примере я указал URL-адрес запроса callback=recover и приступил к реализации function recover(...) {...}.На этот раз мне не нужно беспокоиться об этом.Dojo вставит свою собственную предпочтительную функцию callback=some_function_name_generated_by_dojo.

  3. Я предполагаю, что some_function_name_generated_by_dojo определяется как:

Определение:

function some_function_name_generated_by_dojo(response_from_server) {
    return response_from_server;
}

Конечно, определение не так просто, но преимущество этого подхода состоит в том, что я могу воспользоваться преимуществами Dojo Deferred framework.Посмотрите код ниже, который идентичен предыдущему примеру:

dojo.io.script.get(jsonpArgs).then(function(response_from_server) {
    console.log(response_from_server);
})

Это даст мне точные данные, которые мне нужны:

{
    id: 1234,
    name: Juan,
    data: [
        ["2000-01-01", 1234],
        ["2000-01-02", 5678]
    ]
}
...