Pregunta

Javascript

Por ejemplo, tengo el siguiente código JavaScript (Dojo 1.6 ya está cargado):

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);
}

Consulta directa del navegador

Entiendo que mi servidor recibirá la consulta como si hubiera escrito lo siguiente en la barra de direcciones:

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

Respuesta esperada

Si consulté directamente mi servidor usando la barra de direcciones del navegador, recibiré, en tipo mime application/json y texto sin formato renderizado en el navegador, algo como esto:

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

Problema

Ahora, mirando hacia atrás a la Parte II del JavaScript, ejecutaría la solicitud JSONP con dojo.io.script.get(jsonpArgs). Esto devuelve un Deferred objeto, que puedo aprovechar encadenando .then después de. Tenga en cuenta que definí el manejador para el .then Evento a la producción que capturó data a la consola.

Sin embargo, todo lo que obtengo en la consola es un Event. Traté de buscar en su árbol de datos, pero no pude encontrar los datos que esperaba.

Pregunta

  1. ¿Dónde se almacena la respuesta para una solicitud JSONP? ¿Cómo lo encuentro?
  2. Mi servidor (que controlo) solo genera una representación de texto sin formato de los datos solicitados, envuelto en el callback función (aquí especificada como recover), y especifica un application/json Tipo de Mimica. ¿Hay algo más que necesite configurar en mi servidor, de modo que los datos de respuesta sean capturados por el Deferred ¿objeto?

Intento de solución

De hecho, puedo recuperar la respuesta definiendo la función de devolución de llamada (en este caso recover en la Parte III del JavaScript). Sin embargo, en los tutoriales del dojo, simplemente recuperaron los datos utilizando el Deferred (y .then) estructura. ¿Cómo lo hago usando dojo? Deferred¿s?

Actualización (usando el ejemplo de Twitter del tutorial de Dojo)

Tome, por ejemplo, este guión del tutorial de Dojo, Conseguir Jiggy con JSONP. Lo edité para registrar datos en la consola.

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;
});

Para console.log(data), Obtengo un Object, no un Event como lo ilustra mi caso. Dado que el ejemplo implica que los datos residen en data.results, También trato de navegar por este árbol, pero no veo mis datos esperados de Twitter. Estoy perdido.

Para console.log(data.results), Obtengo una variedad de Objects. Si consulte Twitter directamente, esto es lo que obtendría en texto sin formato. Cada Object Contiene los metadatos de tweet habituales como el nombre de usuario, el tiempo, el retrato de usuario y el tweet en sí. Suficientemente fácil.

Este me golpea directamente en la cabeza. El manejador para el .then la cadena, una función anónima, recibe solo un argumento data. Pero, ¿por qué es que el results propiedad de console.log(data) y el objeto devuelto del que obtengo console.log(data.results) son diferente?

¿Fue útil?

Solución

Lo tengo.

Implementación de devolución de llamada manual

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);

Esta es la solicitud que reciba mi servidor:

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

En este caso, esperaré la siguiente salida de mi servidor:

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

Tres cosas a tener en cuenta:

  1. El servidor esperará callback En la cadena URL de consulta. callback se implementa como una propiedad de jsonpArgs.
  2. Porque especifiqué callback=recover, mi servidor se adjuntará recover( + the_data_I_need + ), devuelve la cadena completa al navegador, y el navegador se ejecutará recover(the_data_I_need). Esto significa...
  3. Que tendré que definir, por ejemplo, function recover(one_argument_only) {doAnythingYouWantWith(one_argument_only)}

El problema con este enfoque es que no puedo aprovechar Deferred encadenado usando .then. Por ejemplo:

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

Esto me dará un Event, sin rastro de la respuesta esperada en absoluto.


Aprovechando la implementación de Dojo de las solicitudes 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);

Esta es la solicitud que reciba mi servidor:

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

En este caso, esperaré la siguiente salida de mi servidor:

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

Cosas a tener en cuenta:

  1. Tenga en cuenta la propiedad de jsonpArgs, callbackParamName. El valor de esta propiedad debe ser el nombre de la variable (en la cadena URL de consulta) esperada por el servidor. Si mi servidor espera callbackfoo, después callbackParamName: "callbackfoo". En mi caso, mi servidor espera el nombre callback, por lo tanto callbackParamName: "callback".

  2. En el ejemplo anterior, especifiqué en la URL de consulta callback=recover y procedió a implementar function recover(...) {...}. Esta vez, no necesito preocuparme por eso. Dojo insertará su propia función preferida callback=some_function_name_generated_by_dojo.

  3. Imagino some_function_name_generated_by_dojo ser definido como:

Definición:

function some_function_name_generated_by_dojo(response_from_server) {
    return response_from_server;
}

Por supuesto, la definición no es tan simple, pero la ventaja de este enfoque es que puedo aprovechar el marco diferido de Dojo. Vea el código a continuación, que es idéntico al ejemplo anterior:

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

Esto me dará los datos exactos que necesito:

{
    id: 1234,
    name: Juan,
    data: [
        ["2000-01-01", 1234],
        ["2000-01-02", 5678]
    ]
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top