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

StackOverflow https://stackoverflow.com/questions/133310

質問

標準の拡張ポイントを提供する 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 コールバックではなく、マザー関数内で。jQuery またはその他のブラウザ内 API を使用して同期 AJAX リクエストを実行する方法はありますか?

役に立ちましたか?

解決

から jQueryのドキュメント:あなたが指定する 非同期 になるオプション 間違い 同期 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
    });
}

他のヒント

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

jQuery.ajaxSetup({async:false});

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

あとは一度電源を入れ直すだけです

jQuery.ajaxSetup({async:true});

@Adamが提案したのと同じことがうまくいくと思いますが、再構成したい人には役立つかもしれません jQuery.get() または jQuery.post() さらに詳しく jQuery.ajax() 構文。

素晴らしい解決策です!これを実装しようとしたときに、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;
}

これらの回答はすべて、async:false を指定して Ajax 呼び出しを実行すると、Ajax リクエストが完了するまでブラウザがハングするという点を見逃しています。フロー制御ライブラリを使用すると、ブラウザをハングアップすることなくこの問題を解決できます。以下にその例を示します フレーム.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();
}
function getURL(url){
    return $.ajax({
        type: "GET",
        url: url,
        cache: false,
        async: false
    }).responseText;
}


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

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

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

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

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

注記:使用すべきではありません async: false 次の警告メッセージが表示されるため、

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

Chrome はコンソールでもこれについて警告します。

メインスレッド上の同期 XMLHttpRequest は、エンド ユーザーのエクスペリエンスに悪影響を及ぼすため、非推奨になりました。さらに詳しいヘルプが必要な場合は、次を確認してください https://xhr.spec.whatwg.org/.

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

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

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

編集クロムは作業中です ページ終了時の同期 XHR の禁止 ユーザーがページから移動するか閉じたとき。これには、アンロード前、アンロード、ページ非表示、可視性変更が含まれます。

これがあなたのユースケースである場合は、これを見てみるとよいでしょう navigator.sendビーコン その代わり

ページで http ヘッダーまたは iframe のallow属性のいずれかを使用して同期要求を無効にすることもできます。

async: false ブラウザがブロックされてしまいます。ノンブロッキング同期ソリューションの場合は、次のものを使用できます。

ES6/ECMAScript2015

ES6 ではジェネレーターと 共同図書館:

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 await を使用できます。

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

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

を追加しました データ・タイプ「JSON」 そして変更しました .responseText応答JSON.

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

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

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

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

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

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

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

これは例です:

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

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

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

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

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

これは、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();

なぜなら 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;
};

これは私の "” 名前空間:

var Thread = {
    sleep: function(ms) {
        var start = Date.now();

        while (true) {
            var clock = (Date.now() - start);
            if (clock >= ms) break;
        }

    }
};

そして、私はそれを次のように呼んでいます。

var d1 = new Date();
console.log('start ' + d1.toLocaleTimeString());
Thread.sleep(10000);
var d2 = new Date();
console.log('end ' + d2.toLocaleTimeString());

コンソールを見ると、次の結果が得られます。

start 1:41:21 PM
end 1:41:31 PM
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top