web-dev-qa-db-ja.com

関数は$ .getJSONが終了するまでreturnで待機します

Embed.ly APIを使用して特定の動画からサムネイル情報を取得する必要がある関数を書いていますが、現在のところ、この関数はAPIからJSON結果を取得する前に値を返します。

次のコードを使用しています。

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

ただし、Chrome JavaScriptコンソールを使用している場合、次のことがわかります。

  1. 関数が呼び出されます
  2. 未定義が返されます
  3. XHRリクエストが終了しました
  4. 可変サムネイルコンテンツがコンソールに表示されます

これは明らかに間違った順序です。

どんな助けでも大歓迎です!

22
xorinzor

回答を更新しました

getJSONはpromise(読み取り専用の据え置き)を返すので、それを聞くことができます。ただし、後処理が必要なため、解決された値を変更できるthenをチェーンする必要があります。

_// 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!
});
_

元の答え

据え置きオブジェクト を使用して、 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!
    });
_

_$.getJSON_の遅延を返して生データを取得できます。ただし、オブジェクトへの「後処理」のため、カスタム遅延が必要です。 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

あなたは簡単に使うことができます$.getJSONのコールバックは次のようになります。

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

   });
}

注:

returnを実行しようとしているところに結果を渡すために関数を呼び出しているのがわかりますが、呼び出し元の関数にreturn結果を返すことはできません。なぜなら、$.getJSONは非同期です。

1
thecodeparadox