2012-07-12 12 views
14

¿Cómo puedo usar jQuery diferidos para retrasar el retorno de la función hasta que se realice una llamada asincrónica dentro de la función completa + obtener valor devuelto?jQuery diferido: usar para retrasar el retorno de la función hasta llamada asincrónica dentro de la función completa + obtener valor de retorno

Este es mi código actual:

function getFields(page) 
{ 
    var dff = $.Deferred(); 
    result = {}; 
    $.ajax(//the async call 
    { 
     url: page, 
     success: 
     function (data) 
     { 
      //work out values for field1 & field 2 from data here 
      result = 
      { 
      'field1' : field1, 
      'field2' : field2 
      }; 
     }, 
     complete: 
     function() 
     { 
      dff.resolve(result); //my attempt to return the result 
     } 
    } 
); 
    return dff.promise(); 
} 

quiero esto para imprimir { "campo1": "campo2" "valor1": "valor2"}

var result = getFields('http://something'); 
console.log(JSON.stringify(result)); 

Sin embargo, el valor del resultado parece ser un objeto jQuery, entonces estoy haciendo algo mal, pero ¿qué?

Gracias!


P.S. Perdón por la pregunta de novato, soy un usuario por primera vez de diferidos, por lo que sigo captando los conceptos básicos.

Respuesta

12

La única manera de retrasar la devolución de su función getFields sería la de establecer la propiedad AJAX async false:

var ajaxPromise = $.ajax(
    { 
     url: page, 
     async: false // make the call synchronous 
    } 
); 

Pero la documentación de jQuery señala que esta está en desuso desde 1.8 en adelante (es decir, su uso es desanimado).

Los aplazados no hacen que AJAX sea síncrono, sino que facilitan el trabajo con devoluciones de llamada y métodos asíncronos.

De lo que puedo decir de lo que usted está tratando de que podría funcionar mejor que hacer algo como esto:

function getFields(page) 
{ 
    var ajaxPromise = $.ajax(//the async call 
    { 
     url: page 
    } 
); 

    var dff = $.Deferred(); 
    ajaxPromise.then(function(data){ 

    // Possibly access the loaded data in this function. 
    var result = { 
     'field1' : field1, 
     'field2' : field2 
    }; 

    // Notify listeners that the AJAX call completed successfully. 
    dff.resolve(result); 

    }, function(){ 
    // Something went wrong - notify listeners: 
    dff.reject(/* possibly pass information about the error */); 
    }); 

    return dff.promise(); 
} 

A continuación, utilice el objeto promesa de esta manera:

var fieldPromise = getFields('http://something'); 
fieldPromise.done(function(result){ 
    console.log(JSON.stringify(result)); 
}); 

Tenga en cuenta que getFields devuelve un objeto Promise inmediatamente, pero debe esperar a que se resuelva la promesa antes de poder cerrar la sesión del resultado.

+0

@ Sly_caridnal: +1 y comprobar - gran explicación! – bguiz

+0

Oooh, nice ... Envolver 'dff.resolve (data);' en un 'setTimeout' es una manera rápida y fácil de simular una llamada lenta de ajax (ya que lo que estoy probando no termina consistentemente antes o después de una segunda llamada ajax) – Izkata

+0

Hay una forma en realidad: cambiar la declaración de retorno de la función 'getFields (page)' como 'return dff.promise(). getState() == 'resolved'' Pausará hasta que se resuelva o rechace. Por supuesto, solo puede devolver el objeto prometido y verificar el estado en otro lugar. – shuangwhywhy

6

Esta es la idea básica de los diferidos: se le devuelve un objeto, y puede usarlo para definir funciones que se invocarán cuando regrese el valor devuelto. Por lo que podría hacer algo como:

function getFields(page) 
{ 
    return $.ajax(page); 
} 

Entonces se le puede llamar y especificar la función que se llamará cuando la llamada XHR completa:

var jqXHR = getFields("/path/to/call"); 
jqXHR.done(function (data) { alert(JSON.stringify(data); }); 

El objeto es chainable, por lo que sólo puede hacer esto :

getFields("/path/to/call") 
    .done(function (data) { alert(JSON.stringify(data); }); 

Tenga en cuenta que el objeto devuelto por jqXHR $.ajax es un objeto diferido-compatibles, para que pueda leer la documentación en http://api.jquery.com/category/deferred-object/.

no estoy seguro de lo que quería decir con su código de muestra (ya que no utiliza realmente la llamada Ajax), pero tal vez que quería decir algo como esto:

function getFields() 
{ 
    var df = $.Deferred(); 
    window.setTimeout(function() { 
     df.resolve({field1: "value1", field2: "value2"}); 
    }, 1000); 
    return df.promise(); 
} 

getFields().done(function (data) { console.log(JSON.stringify(data)); }); 

Esto imprimirá el valor de una deseada segundo después de ejecutarlo.

Cuestiones relacionadas