web-dev-qa-db-fra.com

fonction attendre avec retour jusqu'à ce que $ .getJSON soit terminé

J'écris une fonction qui doit obtenir les informations miniatures d'une vidéo donnée à l'aide de l'API embed.ly, mais actuellement la fonction renvoie une valeur avant même d'obtenir le résultat JSON de l'API.

J'utilise le code suivant:

function getThumbnail(vUrl) {
    var thumbnail   = '';
    var title       = '';
    var caption     = '';
    var content     = '';

    $.when( $.getJSON("http://api.embed.ly/1/oembed?key=:key&url="+vurl) ).then(function(data){
        var thumbnail = data.thumbnail_url;
            console.log(thumbnail);

        return {
            thumbnail:thumbnail,
            vurl:vurl
        }
    });
}

Cependant, lorsque j'utilise la console Chrome Javascript, je peux voir que:

  1. la fonction est appelée
  2. undefined est retourné
  3. La demande XHR est terminée
  4. le contenu des vignettes variables est affiché dans la console

C'est évidemment le mauvais ordre.

Toute aide est grandement appréciée!

22
xorinzor

Réponse mise à jour

getJSON renvoie une promesse (différée en lecture seule), afin que vous puissiez l'écouter. Mais comme vous avez besoin d'un post-traitement, vous voudriez chaîner un then qui vous permet de modifier la valeur résolue.

// Now using `then`
function getThumbnail(vUrl){
  return $.getJSON("http://api.embed.ly/1/oembed?key=:key&url="+vurl).then(function(data){
    return {
      thumbnail:data.thumbnail_url,
      vurl:vurl
    }
  });
}

//and in your call will listen for the custom deferred's done
getThumbnail('the_vurl_').then(function(returndata){
  //received data!
});

Réponse originale

Vous pouvez utiliser un objet différé , et écouter le done() .

function getThumbnail(vUrl) {
    //create our deferred object
    var def = $.Deferred();

    //get our JSON and listen for done
    $.getJSON("http://api.embed.ly/1/oembed?key=:key&url="+vurl)
        .done(function(data){

            //resolve the deferred, passing it our custom data
            def.resolve({
                thumbnail:data.thumbnail_url,
                vurl:vurl
            });
        });

    //return the deferred for listening
    return def;
}

//and in your call will listen for the custom deferred's done
getThumbnail('the_vurl_')
    .done(function(returndata){
        //received data!
    });

Vous pouvez renvoyer $.getJSON Différé pour obtenir les données brutes. Mais en raison du "post-traitement" dans un objet, la personnalisation différée est nécessaire. Vous pouvez également passer un rappel à getThumbnail():

function getThumbnail(vUrl,callback) {
    $.getJSON("http://api.embed.ly/1/oembed?key=:key&url="+vurl,function(returndata){
        callback(returndata);
    });
}

getThumbnail('the_vurl_',function(returndata){
    //received data!
})
29
Joseph

vous pouvez simplement utiliser le rappel de $.getJSON comme suit:

function result(res) {
  console.log(res);
}

function getThumbnail(vUrl) {
   var thumbnail   = '';
   var title       = '';
   var caption     = '';
   var content     = '';

   $.getJSON("http://api.embed.ly/1/oembed?key=:key&url="+vurl, function(data) {
     var thumbnail = data.thumbnail_url;
     console.log(thumbnail);

     var result = {
        thumbnail:thumbnail,
        vurl:vurl
      };

     // passing the result to a function
     getResult(result);

   });
}

REMARQUE:

Vous voyez que j'appelle une fonction pour passer le résultat, où vous essayez de return, mais vous ne pouvez pas return résultat vers la fonction appelante. Parce que, $.getJSON Est asynchrone.

1
thecodeparadox