jquery - mengembalikan nilai menggunakan hasil ajax pada kesuksesan

95

Saya punya masalah kecil dengan fungsi jquery $ .ajax ().

Saya memiliki formulir di mana setiap klik pada tombol radio atau pilihan dari menu tarik-turun membuat variabel sesi dengan nilai yang dipilih.

Sekarang - Saya memiliki salah satu menu tarik-turun yang memiliki 4 opsi - yang pertama (dengan label Tidak Ada) memiliki nilai = "" yang lain memiliki idnya.

Apa yang saya inginkan terjadi adalah pada opsi Tidak Ada (dengan nilai kosong) untuk menghapus sesi dan lainnya untuk membuatnya, tetapi hanya jika sesi dengan nama pilihan khusus ini belum ada - karena semua opsi lain memiliki jumlah yang sama yang ditetapkan padanya - itu hanya menunjukkan mana yang dipilih.

Saya tidak yakin apakah itu masuk akal - tetapi lihat kodenya - mungkin ini akan membuatnya lebih jelas:

$("#add_ons select").change(function() {
        // get current price of the addons
        var order_price_addon = $(".order_price_addon").text();
        // get price of the clicked radio button from the rel attribute
        var add = $(this).children('option').attr('label');
        var name = $(this).attr('name');
        var val = $(this).val();


        if(val == "") {
            var price = parseInt(order_price_addon) - parseInt(add);
            removeSession(name);
        } else {
            if(isSession(name) == 0) {
                var price = parseInt(order_price_addon) + parseInt(add);
            }   
            setSession(name, val);              
        }

        $(".order_price_addon").html(price);    
        setSession('order_price_addon', price);         
        updateTotal();
});

jadi - pertama-tama ketika #add_ons menu pilih memicu "perubahan" kami mendapatkan beberapa nilai dari beberapa elemen untuk kalkulasi.

kami mendapatkan atribut label opsi dari pilihan kami yang menyimpan nilai yang akan ditambahkan ke total, nama yang dipilih untuk membuat sesi dengan nama ini dan nilai untuk kemudian memeriksa mana yang dipilih.

sekarang - kami memeriksa apakah val == "" (yang menunjukkan bahwa opsi Tidak Ada telah dipilih) dan kami mengurangi jumlah dari total serta menghapus sesi dengan nama yang dipilih.

Setelah ini masalah dimulai - pernyataan lain.

Lain - kami ingin memeriksa apakah fungsi isSession () dengan nama selektor kami mengembalikan 0 atau 1 - jika mengembalikan 0 maka kami menambahkan ke total nilai yang disimpan dalam atribut label, tetapi jika mengembalikan 1 - itu akan menyarankan sesi tersebut sudah ada - maka kami hanya mengubah nilai sesi ini dengan membuatnya kembali - tetapi jumlahnya tidak ditambahkan ke dalamnya.

Sekarang fungsi isSession terlihat seperti ini:

function isSession(selector) {
    $.ajax({
        type: "POST",
        url: '/order.html',
        data: ({ issession : 1, selector: selector }),
        dataType: "html",
        success: function(data) {
            return data;
        },
        error: function() {
            alert('Error occured');
        }
    });
}

Sekarang - masalahnya adalah - saya tidak tahu apakah menggunakan "return" akan mengembalikan hasil dari fungsi - karena tampaknya tidak berhasil - namun, jika saya meletakkan "data" di bagian yang berhasil: waspada - tampaknya mengembalikan nilai yang benar.

Adakah yang tahu bagaimana mengembalikan nilai dari fungsi dan kemudian membandingkannya di pernyataan berikutnya?


Thanks guys - Saya sudah mencobanya dengan cara berikut:

function isSession(selector) {
    $.ajax({
        type: "POST",
        url: '/order.html',
        data: ({ issession : 1, selector: selector }),
        dataType: "html",
        success: function(data) {
            updateResult(data);
        },
        error: function() {
            alert('Error occured');
        }
    });
}

lalu fungsi updateResult ():

function updateResult (data) {result = data; }

hasil - adalah variabel global - yang kemudian saya coba baca:

$("#add_ons select").change(function() {
        // get current price of the addons
        var order_price_addon = $(".order_price_addon").text();
        // get price of the clicked radio button from the rel attribute
        var add = $(this).children('option').attr('label');
        var name = $(this).attr('name');
        var val = $(this).val();


        if(val == "") {
            var price = parseInt(order_price_addon) - parseInt(add);
            removeSession(name);
        } else {
            isSession(name);
            if(result == 0) {
                var price = parseInt(order_price_addon) + parseInt(add);
            }   
            setSession(name, val);              
        }

        $(".order_price_addon").html(price);    
        setSession('order_price_addon', price);         
        updateTotal();
    });

tetapi untuk beberapa alasan - tidak berhasil - ada ide?

pengguna398341
sumber
Ini dapat membantu memecahkan masalah ini: stackoverflow.com/questions/14220321/…
mirzaei.sajad

Jawaban:

114

Masalahnya adalah Anda tidak dapat mengembalikan nilai dari panggilan asinkron, seperti permintaan AJAX, dan mengharapkannya berfungsi.

Alasannya adalah bahwa kode yang menunggu respons telah dieksekusi pada saat respons diterima.

Solusi untuk masalah ini adalah dengan menjalankan kode yang diperlukan di dalam success:callback. Dengan cara itu hanya mengakses dataketika tersedia.

function isSession(selector) {
    $.ajax({
        type: "POST",
        url: '/order.html',
        data: ({ issession : 1, selector: selector }),
        dataType: "html",
        success: function(data) {
            // Run the code here that needs
            //    to access the data returned
            return data;
        },
        error: function() {
            alert('Error occured');
        }
    });
}

Kemungkinan lain (yang secara efektif adalah hal yang sama) adalah memanggil fungsi di dalam success:callback Anda yang meneruskan data saat tersedia.

function isSession(selector) {
    $.ajax({
        type: "POST",
        url: '/order.html',
        data: ({ issession : 1, selector: selector }),
        dataType: "html",
        success: function(data) {
                // Call this function on success
            someFunction( data );
            return data;
        },
        error: function() {
            alert('Error occured');
        }
    });
}

function someFunction( data ) {
    // Do something with your data
}
pengguna113716
sumber
12
Anda BISA mengembalikan nilai dari permintaan AJAX, tetapi itu hanya jika Anda membuatnya non-asinkron (setel opsi async: false). Dalam beberapa kasus, memiliki panggilan asinkron tidak diwajibkan. Lebih lanjut tentang jquery.ajax () doc api.jquery.com/jQuery.ajax , bukan ituAs of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is deprecated;
Adrien Be
48
"Non-asynchronous" tentu saja juga dapat disebut sebagai "sinkron";)
Charles Wood
dalam kedua metode yang Anda sarankan; yaitu. menjalankan fungsi dengan sukses, maka Anda harus menulis banyak ajax untuk skenario yang berbeda. ini tidak akan membantu dalam membuat pembungkus ajax global, mesin.
wpcoder
Tampaknya, async: false sekarang sudah tidak digunakan lagi dan semua pemrosesan perlu dilakukan dalam fungsi callback.
Puneet Lamba
32

Ada banyak cara untuk mendapatkan respons jQuery AJAX. Saya berbagi dengan Anda dua pendekatan umum:

Pertama:

gunakan async = false dan dalam fungsi kembalikan ajax-object dan kemudian dapatkan respons ajax-object.responseText

/**
 * jQuery ajax method with async = false, to return response
 * @param  {mix}  selector - your selector
 * @return {mix}           - your ajax response/error
 */
function isSession(selector) {
    return $.ajax({
        type: "POST",
        url: '/order.html',
        data: {
            issession: 1,
            selector: selector
        },
        dataType: "html",
        async: !1,
        error: function() {
            alert("Error occured")
        }
    });
}
// global param
var selector = !0;
// get return ajax object
var ajaxObj = isSession(selector);
// store ajax response in var
var ajaxResponse = ajaxObj.responseText;
// check ajax response
console.log(ajaxResponse);
// your ajax callback function for success
ajaxObj.success(function(response) {
    alert(response);
});

Kedua:

gunakan metode $ .extend dan buat fungsi baru seperti ajax

/**
 * xResponse function
 *
 * xResponse method is made to return jQuery ajax response
 * 
 * @param  {string} url   [your url or file]
 * @param  {object} your ajax param
 * @return {mix}       [ajax response]
 */
$.extend({
    xResponse: function(url, data) {
        // local var
        var theResponse = null;
        // jQuery ajax
        $.ajax({
            url: url,
            type: 'POST',
            data: data,
            dataType: "html",
            async: false,
            success: function(respText) {
                theResponse = respText;
            }
        });
        // Return the response text
        return theResponse;
    }
});

// set ajax response in var
var xData = $.xResponse('temp.html', {issession: 1,selector: true});

// see response in console
console.log(xData);

Anda dapat membuatnya sebesar yang Anda inginkan ...

Neeraj Singh
sumber
Ide bagus tetapi ajaxObj['responseText']tidak ada saat Anda menentukanvar ajaxResponse
mu3
Sempurna!! solusi pertama Anda menyelamatkan saya
Kallel Omar
metode kedua adalah 100% A OK! ;)
Schalk Keun
7
Mulai jQuery 1.8, penggunaan async: false sudah tidak digunakan lagi!
gatteo
10

Saya melihat jawabannya di sini dan meskipun membantu, mereka tidak persis seperti yang saya inginkan karena saya harus mengubah banyak kode saya.

Apa yang berhasil bagi saya adalah melakukan sesuatu seperti ini:

function isSession(selector) {
    //line added for the var that will have the result
    var result = false;
    $.ajax({
        type: "POST",
        url: '/order.html',
        data: ({ issession : 1, selector: selector }),
        dataType: "html",
        //line added to get ajax response in sync
        async: false,
        success: function(data) {
            //line added to save ajax response in var result
            result = data;
        },
        error: function() {
            alert('Error occured');
        }
    });
    //line added to return ajax response
    return result;
}

Harapan membantu seseorang

anakin

anakin
sumber
4
Anda sebenarnya baru saja menonaktifkan asinkron
Weijing Jay Lin
5

Meskipun semua pendekatan mengenai penggunaan async: falsetidak baik karena penghentiannya dan halaman macet sampai permintaan kembali. Berikut adalah 2 cara untuk melakukannya:

1st: Mengembalikan seluruh respons ajax dalam suatu fungsi dan kemudian menggunakan donefungsi untuk menangkap respons saat permintaan selesai. (DIREKOMENDASIKAN, CARA TERBAIK)

function getAjax(url, data){
    return $.ajax({
        type: 'POST',
        url : url,              
        data: data,
        dataType: 'JSON',
        //async: true,  //NOT NEEDED
        success: function(response) {
            //Data = response;
        }
    });
 }

HUBUNGI YANG DI ATAS SEPERTI:

getAjax(youUrl, yourData).done(function(response){
    console.log(response);
});

UNTUK PANGGILAN GANDA AJAX MENGGUNAKAN $.when:

$.when( getAjax(youUrl, yourData), getAjax2(yourUrl2, yourData2) ).done(function(response){
    console.log(response);
});

2: Simpan respons dalam cookie dan kemudian di luar panggilan ajax dapatkan nilai cookie itu. (TIDAK DIANJURKAN)

        $.ajax({
            type: 'POST',
            url : url,              
            data: data,
            //async: false,    // No need to use this
            success: function(response) {
                Cookies.set(name, response);
            }
        });

        // Outside of the ajax call
        var response = Cookies.get(name);

CATATAN: Pada jquery cookieslibrary exmple di atas digunakan, ini cukup ringan dan berfungsi sebagai snappy. Ini tautannya https://github.com/js-cookie/js-cookie

MR_AMDEV
sumber
3

Tambahkan async: falseke daftar atribut Anda. Ini memaksa utas javascript untuk menunggu sampai nilai yang dikembalikan diambil sebelum melanjutkan. Jelas, Anda tidak ingin melakukan ini dalam setiap keadaan, tetapi jika nilai diperlukan sebelum melanjutkan, ini akan berhasil.

Penjahat
sumber
4
Anda seharusnya tidak pernah mengatur async: false. Ini memblokir semua yang ada di halaman selama pengambilan. Anda tahu apa singkatan dari A di AJAX: Asynchronous. Jawaban yang tepat adalah OP perlu menggunakan success()callback dengan benar.
nietonfir
2
Saya mengakui fakta bahwa semuanya harus menunggu. Dalam keadaan tertentu, fungsi pemanggil mungkin memerlukan nilai yang dikembalikan, seperti menambahkan catatan baru dan memerlukan ID catatan yang dikembalikan. Begitu Anda mengetahui aturannya, Anda tahu kapan aturan itu bisa dilanggar. Jangan pernah bilang tidak akan pernah. Inilah orang lain yang setuju. ( stackoverflow.com/questions/3880361/… )
Preman
1
@CharlesWood Hanya untuk mereka yang tidak dapat memahami sifat asinkron dari ajax.
nietonfir
1
@nietonfir: jika Anda tidak pernah menggunakan async: falsemengapa jQuery menerapkan opsi ini? jika saya tidak memuat data dalam jumlah besar ke halaman dan hanya menangani peristiwa pengguna, tidak masalah jika hal itu memblokir semua yang lain dalam waktu singkat untuk pengguna tersebut. tidak ada yang salah dan tidak ada yang buruk tentang itu. (jika digunakan dengan benar itu tidak akan memblokir apa pun karena dalam waktu itu tidak ada tindakan lain untuk pengguna tertentu yang akan terjadi)
low_rents
1
@northkildonan Tidak, itu tidak baik. Permintaan sinkronisasi AJAX buruk. Ini memblokir utas javascript lengkap dengan sesuatu yang tidak dapat Anda kendalikan. Anda tidak memiliki kendali atas jumlah waktu yang diperlukan untuk memproses permintaan: koneksi mungkin tidak dapat diandalkan, server mungkin membutuhkan waktu lebih lama dari yang diharapkan, dll. Satu- satunya alasan ada di jQuery adalah Anda mungkin perlu menyimpan data on page unload (satu-satunya tempat yang tidak terlalu penting jika memakan waktu lebih lama, karena pengguna sudah menyatakan keinginannya untuk meninggalkan halaman). Lihat saja unit test jQuery…
nietonfir
3

Ini sudah cukup tua, dan jelek, jangan lakukan ini. Anda harus menggunakan callback: https://stackoverflow.com/a/5316755/591257
Memiliki masalah yang sama, menyelesaikannya dengan cara ini, menggunakan var global. Tidak yakin apakah itu yang terbaik tapi pasti berhasil. Jika terjadi kesalahan, Anda mendapatkan string kosong (myVar = ''), sehingga Anda dapat menanganinya sesuai kebutuhan.

var myVar = '';
function isSession(selector) {
  $.ajax({
    'type': 'POST',
    'url': '/order.html',
    'data': {
      'issession': 1,
      'selector': selector
    },
    'dataType': 'html',
    'success': function(data) {
      myVar = data;
    },
    'error': function() {
      alert('Error occured');
    }
  });
  return myVar;
}
aesede
sumber
4
Anda juga perlu menambahkan di async: falsesini, karena dalam mode asynchronous tidak ada jaminan yang datadisimpan ke myVarsebelum myVardikembalikan.
low_rents
2
// Common ajax caller
function AjaxCall(url,successfunction){
  var targetUrl=url;
  $.ajax({
    'url': targetUrl,
    'type': 'GET',
    'dataType': 'json',
    'success': successfunction,
    'error': function() {
      alert("error");
    }
  });
}

// Calling Ajax
$(document).ready(function() {
  AjaxCall("productData.txt",ajaxSuccessFunction);
});

// Function details of success function
function ajaxSuccessFunction(d){
  alert(d.Pioneer.Product[0].category);
}

mungkin membantu, membuat fungsi panggilan ajax umum dan melampirkan fungsi yang memanggil ketika berhasil panggilan ajax, lihat contoh

Binson
sumber
1

Dengan Bantuan dari sini

function get_result(some_value) {
   var ret_val = {};
   $.ajax({
       url: '/some/url/to/fetch/from',
       type: 'GET',
       data: {'some_key': some_value},
       async: false,
       dataType: 'json'
   }).done(function (response) {
       ret_val = response;
   }).fail(function (jqXHR, textStatus, errorThrown) {
           ret_val = null;
       });
   return ret_val;
}

Semoga ini sedikit membantu seseorang di suatu tempat.

Muhammad Nahid
sumber
Penggunaannya async: false,prasejarah dan tidak digunakan lagi sejak jQuery v1.8, Ini mungkin tidak akan membantu siapa pun
Alon Eitan
-2

Hai, coba async: false dalam panggilan ajax Anda ..

kathir
sumber