jQueryに非同期ではなく同期のAjaxリクエストを実行させるにはどうすればよいですか?


1208

標準の拡張ポイントを提供するJavaScriptウィジェットがあります。それらの1つはbeforecreate関数です。falseアイテムが作成されないように戻る必要があります。

jQueryを使用して、この関数にAjax呼び出しを追加しました。

beforecreate: function (node, targetNode, type, to) {
  jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),

  function (result) {
    if (result.isOk == false) 
        alert(result.message);
  });
}

しかし、ウィジェットがアイテムを作成しないようにしたいのでfalse、コールバックではなく、mother関数に戻る必要があります。jQueryまたはその他のブラウザー内APIを使用して同期AJAX要求を実行する方法はありますか?


30
それを解決する適切な方法は、ウィジェットの拡張ポイントの使用に関する約束を書き換えることです。このようにすると、非同期アクション(ajaxリクエストなど)をとして簡単に設定できますbeforecreate
Kos

3
サジャク機能を提案します。Tの文字はありますか?はい、バンナ、3 Tをください。
Cody O'Dell 2016

2
@Kosがスポットです。Sync XHRはここでは必要ありません
Michael Westcott

1
JavaScriptを開始するときに人々が私に1つのアドバイスを求めた場合、私は次のように言います。JavaScriptの非同期文字を受け入れ、それと戦うことはしないでください。
Emmanuelの遅延'12

3
この質問は、「ユーザーパスワードをプレーンテキストで保存するにはどうすればよいですか?」確かに答えはありますが、しないでください。
Vectorjohn 2018年

回答:


1165

jQueryのドキュメントから:非同期オプションをfalseに指定して、同期Ajaxリクエストを取得します。その後、コールバックは、母関数が処理される前にデータを設定できます。

提案されたように変更すると、コードは次のようになります。

beforecreate: function (node, targetNode, type, to) {
    jQuery.ajax({
        url: 'http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),
        success: function (result) {
            if (result.isOk == false) alert(result.message);
        },
        async: false
    });
}

97
正確には、同期呼び出しにget()、post()、load()を使用することは不可能です。ajax()のみに「async」パラメーターがあり、「false」に設定できます。
SLA80 2010年

39
@ SLA80いいえ。jQueryの1.1以降:stackoverflow.com/questions/6849686/...
StuperUser

16
@qualidafial私のコメントはSLA80の誤ったコメントを対象としています。同期呼び出しにはget()、post()、load()を使用できます。
StuperUser 2012年

9
async falseはjQuery 1.8以上ではサポートされなくなりました。api.jquery.com/jQuery.ajax
ken

22
@ken async: falseはjQuery 1.8 以降で引き続きサポートされています。async: falsejqXHR($.Deferred)で使用する機能は廃止されました。つまり、従来のメソッドではなく、新しい成功/エラー/完了コールバックオプションを使用する必要がありますjqXHR.done()
ベンジョンソン

255

次の呼び出しにより、jQueryのAjaxセットアップを同期モードにすることができます。

jQuery.ajaxSetup({async:false});

次に、Ajax呼び出しを使用して実行します jQuery.get( ... );

その後、もう一度もう一度オンにします

jQuery.ajaxSetup({async:true});

@Adamによって提案されたものと同じように機能すると思いますが、自分の構文を再構成したい人jQuery.get()jQuery.post()、より複雑なjQuery.ajax()構文に役立つかもしれません。


56
これは非常に悪い考えですが、なぜグローバルレベルで設定するのでしょうか。その後、それを解除することを余儀なくされますか?
ファンメンデス2014

11
少なくとも、これは最良の悪い考えです。「代わりに方法はありません$.ajax()」と言う代わりに。;)
Rzassar 2016年

136

優れたソリューション!実装しようとしたときに、success句で値を返すと、未定義として返されることに気付きました。それを変数に格納して、その変数を返す必要がありました。これは私が思いついた方法です:

function getWhatever() {
  // strUrl is whatever URL you need to call
  var strUrl = "", strReturn = "";

  jQuery.ajax({
    url: strUrl,
    success: function(html) {
      strReturn = html;
    },
    async:false
  });

  return strReturn;
}

16
これは、からではなく、コールバックから値を返していたためですgetWhatever。したがって、あなたは返され何もつまりundefinedあなたからgetWhatever
2011

6
これは絶対に間違っています。'strReturn'を返すときに非同期呼び出しが終了したかどうかはわかりません。
トーマスフリッツ

61
これは同期呼び出しです(async:false)。
Jamesがインディ

85

これらすべての答えは、async:falseを指定してAjax呼び出しを行うと、Ajaxリクエストが完了するまでブラウザがハングするという点を逃しています。フロー制御ライブラリを使用すると、ブラウザをハングアップさせることなくこの問題を解決できます。Frame.jsの例を次に示します。

beforecreate: function(node,targetNode,type,to) {

    Frame(function(next)){

        jQuery.get('http://example.com/catalog/create/', next);
    });

    Frame(function(next, response)){

        alert(response);
        next();
    });

    Frame.init();
}

4
同期呼び出しは、RESTバックエンドのクイックテストハーネスをまとめたい場合や、コールバック地獄よりも単純さを好む場合に便利です。
Distortum、2014年

50
function getURL(url){
    return $.ajax({
        type: "GET",
        url: url,
        cache: false,
        async: false
    }).responseText;
}


//example use
var msg=getURL("message.php");
alert(msg);

10
ただし、「メインスレッドでの同期XMLHttpRequestは、エンドユーザーのエクスペリエンスに悪影響を与えるため、推奨されません。」
ハリ

5
@Hariメインスレッドを使用せずにjQueryを使用して同期ajax呼び出しを実行する方法は何ですか?
Jose Nobile 2016

7
この答えが提供するものがあるとは思わない、それは関数にラップされて4年後に答えられた受け入れられた答えにすぎない。関数がそれが何をするかを示さないので、人々にC + Pを助言することは悪いことです。「それでgetURLvs get?なぜブラウザがハングするのですか?」など
moopet 2016年

27

注:async: falseこの警告メッセージのため、使用しないでください。

Gecko 30.0(Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27)以降、ユーザーエクスペリエンスへの悪影響のため、メインスレッドでの同期リクエストは廃止されました。

Chromeはコンソールでこれについてさえ警告します:

メインスレッドでの同期XMLHttpRequestは、エンドユーザーのエクスペリエンスに悪影響を与えるため非推奨です。詳細については、https://xhr.spec.whatwg.org/を確認してください

このようなことをしていると、いつでも機能しなくなる可能性があるため、ページが壊れる可能性があります。

同期していてもブロックされないように感じる方法で実行したい場合は、async / awaitを使用し、おそらく新しいFetch API などのpromiseに基づいたajaxも使用する必要があります

async function foo() {
  var res = await fetch(url)
  console.log(res.ok)
  var json = await res.json()
  console.log(json)
}

ユーザーがページを移動したり閉じたりしたときに、ページの閉じるときに同期XHRを許可ないようにクロムを編集しています。これには、beforeunload、unload、pagehide、visibilitychangeが含まれます。

これがあなたのユースケースである場合は、代わりにnavigator.sendBeaconを確認することをお勧めします

ページがhttpヘッダーまたはiframeの許可属性のいずれかで同期要求を無効にすることも可能です


非同期エラーをキャッチするにawait fetch(url)は、呼び出しをtry... catchブロックでラップする必要があることに注意してください。
イノスティア2017

4
関数fooはasync、最初に単語を使用するだけでプロミスに変換されたので、それfoo().catch(...)をキャッチすることもできます
Endless

ChromeはすでにAJAX内部のページ非同期(async)禁止beforeunloadが、その後負のフィードバックの後に変更背中を元に戻すbugs.chromium.org/p/chromium/issues/detail?id=952452
アレックス

26

JSONPを使用して)クロスドメインのAjax呼び出しを行っている場合- 同期的に行うことができない場合、asyncフラグはjQueryによって無視されます。

$.ajax({
    url: "testserver.php",
    dataType: 'jsonp', // jsonp
    async: false //IGNORED!!
});

JSONP呼び出しの場合、次を使用できます。

  1. 自分のドメインへのAjax呼び出し-サーバー側でクロスドメイン呼び出しを行う
  2. 非同期で動作するようにコードを変更する
  3. Frame.js(この回答)のような「関数シーケンサー」ライブラリを使用します
  4. 実行をブロックする代わりにUIをブロックします(この答え)(私のお気に入りの方法)

12

ではasync: false、あなた自身にブロックされたブラウザを取得します。非ブロッキング同期ソリューションの場合、以下を使用できます。

ES6 / ECMAScript2015

ES6では、ジェネレーターとcoライブラリーを使用できます。

beforecreate: function (node, targetNode, type, to) {
    co(function*(){  
        let result = yield jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value));
        //Just use the result here
    });
}

ES7

ES7では、asycをそのまま使用できます。

beforecreate: function (node, targetNode, type, to) {
    (async function(){
        let result = await jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value));
        //Just use the result here
    })(); 
}

3
async functionbeforecreateに渡して beforecreate: async function(....、自己呼び出しの非同期関数を削除することができます
Daniel Krom

12

Carcioneからの回答を使用し、JSONを使用するように変更しました。

 function getUrlJsonSync(url){

    var jqxhr = $.ajax({
        type: "GET",
        url: url,
        dataType: 'json',
        cache: false,
        async: false
    });

    // 'async' has to be 'false' for this to work
    var response = {valid: jqxhr.statusText,  data: jqxhr.responseJSON};

    return response;
}    

function testGetUrlJsonSync()
{
    var reply = getUrlJsonSync("myurl");

    if (reply.valid == 'OK')
    {
        console.dir(reply.data);
    }
    else
    {
        alert('not valid');
    }    
}

私は、追加のdataType「JSON」を、変更.responseTextをするresponseJSON

また、返されたオブジェクトのstatusTextプロパティを使用してステータスを取得しました。これはAjax応答のステータスであり、JSONが有効かどうかではないことに注意してください。

バックエンドは正しい(整形式)JSONで応答を返す必要があります。そうしないと、返されるオブジェクトは未定義になります。

元の質問に答える際に考慮すべき2つの側面があります。1つは(async:falseを設定することにより)同期的に実行するようにAjaxに指示することであり、もう1つはコールバック関数ではなく、呼び出し関数のreturnステートメントを介して応答を返すことです。

POSTでも試してみましたが、うまくいきました。

GETをPOSTに変更してデータを追加しました:postdata

function postUrlJsonSync(url, postdata){

    var jqxhr = $.ajax({
        type: "POST",
        url: url,
        data: postdata,
        dataType: 'json',
        cache: false,
        async: false
    });

    // 'async' has to be 'false' for this to work
    var response = {valid: jqxhr.statusText,  data: jqxhr.responseJSON};

    return response;
}

上記のコードは、asyncfalseの場合にのみ機能することに注意してください。async:trueを設定した場合、返されたオブジェクトjqxhrは、AJAX呼び出しが戻った時点では有効ではなく、非同期呼び出しが終了した後でのみ有効ですが、応答変数を設定するには遅すぎます。


7

これは例です:

$.ajax({
  url: "test.html",
  async: false
}).done(function(data) {
   // Todo something..
}).fail(function(xhr)  {
   // Todo something..
});

1
async falsepromiseベースのソリューションで使用するポイントは何ですか。これはブラウザをロックするだけで、何のメリットもありません。
コーディング

2
@GoneCoding正確なシーケンスでコードを実行したい状況があります。その状況ではasync falseを使用できます
Nikki

1
@ニッキ:それは絶対にそれらを連続して実行する方法ではありません。非同期プロミス(ajax呼び出しが既に戻る)と(.then()またはdone()既に示しているように)を使用します。ブラウザをロックすると、ユーザーエクスペリエンスが非常に低下します。async: falseこの例で言ったように、時間の無駄です。
コーディングを

4

最初に、いつ$ .ajaxを使用し、いつ$ .get / $。postを使用するかを理解する必要があります。

リクエストヘッダー設定、キャッシュ設定、同期設定など、ajaxリクエストを低レベルで制御する必要がある場合は、$。ajaxを使用する必要があります。

$ .get / $。post:ajaxリクエストを低レベルで制御する必要がない場合。サーバーへのデータの単純なget / postのみ。の略記

$.ajax({
  url: url,
  data: data,
  success: success,
  dataType: dataType
});

したがって、$。get / $。postでは他の機能(同期、キャッシュなど)を使用できません。

したがって、ajaxリクエストに対する低レベルの制御(同期、キャッシュなど)の場合、$。ajax

 $.ajax({
     type: 'GET',
      url: url,
      data: data,
      success: success,
      dataType: dataType,
      async:false
    });

2

これは、jQueryを使用したASYNCリクエストの簡単な実装です。これが誰にも役立つことを願っています。

var queueUrlsForRemove = [
    'http://dev-myurl.com/image/1', 
    'http://dev-myurl.com/image/2',
    'http://dev-myurl.com/image/3',
];

var queueImagesDelete = function(){

    deleteImage( queueUrlsForRemove.splice(0,1), function(){
        if (queueUrlsForRemove.length > 0) {
            queueImagesDelete();
        }
    });

}

var deleteImage = function(url, callback) {
    $.ajax({
        url: url,
        method: 'DELETE'
    }).done(function(response){
        typeof(callback) == 'function' ? callback(response) : null;
    });
}

queueImagesDelete();

2

XMLHttpReponse同期操作は非推奨であるため、ラップする次のソリューションを思いつきましたXMLHttpRequest。これにより、本質的に非同期のままで、順序付けされたAJAXクエリが可能になります。これは、使い捨てのCSRFトークンに非常に役立ちます。

また、透過的であるため、jQueryなどのライブラリはシームレスに動作します。

/* wrap XMLHttpRequest for synchronous operation */
var XHRQueue = [];
var _XMLHttpRequest = XMLHttpRequest;
XMLHttpRequest = function()
{
  var xhr   = new _XMLHttpRequest();
  var _send = xhr.send;

  xhr.send = function()
  {
    /* queue the request, and if it's the first, process it */
    XHRQueue.push([this, arguments]);
    if (XHRQueue.length == 1)
      this.processQueue();
  };

  xhr.processQueue = function()
  {
    var call = XHRQueue[0];
    var xhr  = call[0];
    var args = call[1];

    /* you could also set a CSRF token header here */

    /* send the request */
    _send.apply(xhr, args);
  };

  xhr.addEventListener('load', function(e)
  {
    /* you could also retrieve a CSRF token header here */

    /* remove the completed request and if there is more, trigger the next */
    XHRQueue.shift();
    if (XHRQueue.length)
      this.processQueue();
  });

  return xhr;
};

-1

元の質問はしていましたのでjQuery.get、それは(前述のようにすることをここで言及する価値があるここでは)1は、可能性が使用async: false中で$.get()はなく、理想的に避ける非同期であるため、それをXMLHTTPRequest推奨されていません(とブラウザが警告を与える可能性が):

$.get({
  url: url,// mandatory
  data: data,
  success: success,
  dataType: dataType,
  async:false // to make it synchronous
});

1
なぜこれが反対投票されたのですか?
alias51

-2

asyn:false同期させるためにajaxリクエストで設定します。

次にコードサンプルを示します。

 $.ajax({
    url: 'some_url',
    type: "GET",
    async: false,
    cache: false,
    dataType: "JSON",
    data: { 
      "p1": v1, 
      "p2": v2
    },
    success: function(result) {
    }  
  }
});

これにより、画面が応答しなくなる可能性があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.