jquery - ส่งคืนค่าโดยใช้ ajax ผลลัพธ์ต่อความสำเร็จ


97

ฉันมีปัญหาเล็กน้อยกับฟังก์ชัน jquery $ .ajax ()

ฉันมีแบบฟอร์มที่ทุกการคลิกบนปุ่มตัวเลือกหรือการเลือกจากเมนูแบบเลื่อนลงจะสร้างตัวแปรเซสชันพร้อมค่าที่เลือก

ตอนนี้ - ฉันมีหนึ่งในเมนูแบบเลื่อนลงซึ่งมี 4 ตัวเลือกเมนูแรก (ที่มีป้ายกำกับไม่มี) มีค่า = "" อื่น ๆ มีรหัส

สิ่งที่ฉันต้องการให้เกิดขึ้นคือตัวเลือกไม่มี (มีค่าว่าง) เพื่อลบเซสชันและอื่น ๆ เพื่อสร้างขึ้น แต่เฉพาะในกรณีที่ไม่มีเซสชันที่มีชื่อเลือกเฉพาะนี้อยู่แล้วเนื่องจากตัวเลือกอื่น ๆ ทั้งหมดมีจำนวนเท่ากันที่กำหนดให้ - เป็นเพียงการระบุว่ารายการใดถูกเลือก

ฉันไม่แน่ใจว่ามันสมเหตุสมผลหรือไม่ แต่ลองดูโค้ด - บางทีนี่อาจทำให้ชัดเจนขึ้น:

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

ดังนั้น - ก่อนอื่นเมื่อเมนู #add_ons select ทริกเกอร์ "เปลี่ยน" เราจะได้รับค่าบางอย่างจากองค์ประกอบบางอย่างสำหรับการคำนวณ

เราได้รับแอตทริบิวต์ป้ายกำกับของตัวเลือกจากการเลือกของเราซึ่งเก็บค่าที่จะเพิ่มลงในผลรวมชื่อของการเลือกเพื่อสร้างเซสชันด้วยชื่อและค่านี้เพื่อตรวจสอบในภายหลังว่ามีการเลือกอันใด

ตอนนี้ - เราตรวจสอบว่า val == "" (ซึ่งจะบ่งบอกว่าไม่มีตัวเลือกถูกเลือก) และเราหักจำนวนเงินออกจากยอดรวมและลบเซสชันที่มีชื่อของผู้เลือก

หลังจากนี้คือจุดเริ่มต้นของปัญหา - else คำสั่ง

อื่น ๆ - เราต้องการตรวจสอบว่าฟังก์ชัน isSession () ที่มีชื่อตัวเลือกของเราส่งคืน 0 หรือ 1 - หากส่งกลับ 0 เราจะบวกค่าทั้งหมดที่เก็บไว้ในแอตทริบิวต์ label แต่ถ้าส่งกลับ 1 - นั่นจะแนะนำ เซสชันนั้นมีอยู่แล้ว - จากนั้นเราจะเปลี่ยนเฉพาะค่าของเซสชันนี้โดยการสร้างใหม่ - แต่จะไม่เพิ่มจำนวนเข้าไป

ตอนนี้ฟังก์ชัน isSession มีลักษณะดังนี้:

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

ตอนนี้ - ปัญหาคือ - ฉันไม่รู้ว่าการใช้ "return" จะส่งคืนผลลัพธ์จากฟังก์ชันหรือไม่เพราะดูเหมือนจะไม่ได้ผล - อย่างไรก็ตามหากฉันใส่ "data" ในความสำเร็จ: ส่วนใน การแจ้งเตือน - ดูเหมือนว่าจะคืนค่าที่ถูกต้อง

มีใครทราบวิธีการคืนค่าจากฟังก์ชันแล้วนำไปเปรียบเทียบในคำสั่งถัดไป


ขอบคุณ - ฉันได้ลองทำตามวิธีต่อไปนี้:

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

จากนั้นฟังก์ชั่น updateResult ():

ฟังก์ชัน updateResult (ข้อมูล) {result = data; }

ผลลัพธ์ - คือตัวแปรทั่วโลก - ซึ่งฉันพยายามอ่านแล้ว:

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

แต่ด้วยเหตุผลบางอย่าง - มันใช้ไม่ได้ - มีความคิดอย่างไร?



อาจช่วยแก้ปัญหานี้ได้: stackoverflow.com/questions/14220321/…
mirzaei.sajad

คำตอบ:


115

ปัญหาคือคุณไม่สามารถส่งคืนค่าจากการโทรแบบอะซิงโครนัสเช่นคำขอ AJAX และคาดว่าจะใช้งานได้

เหตุผลก็คือโค้ดที่รอการตอบกลับได้ดำเนินการตามเวลาที่ได้รับการตอบกลับแล้ว

วิธีแก้ปัญหานี้คือการเรียกใช้รหัสที่จำเป็นภายในการsuccess:โทรกลับ วิธีนี้คือการเข้าถึงdataเฉพาะเมื่อพร้อมใช้งาน

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

ความเป็นไปได้อีกอย่างหนึ่ง (ซึ่งเป็นสิ่งเดียวกันอย่างมีประสิทธิภาพ) คือการเรียกใช้ฟังก์ชันภายในการsuccess:เรียกกลับของคุณที่ส่งผ่านข้อมูลเมื่อพร้อม

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
}

12
คุณสามารถส่งคืนค่าจากการร้องขอ AJAX ได้ แต่นั่นก็ต่อเมื่อคุณกำหนดให้ไม่ใช่แบบอะซิงโครนัส (ตั้งค่าตัวเลือกasync: false) ในบางกรณีไม่จำเป็นต้องมีการโทรแบบอะซิงโครนัส เพิ่มเติมเกี่ยวกับ jquery.ajax () doc api.jquery.com/jQuery.ajaxไม่ใช่อย่างนั้นAs of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is deprecated;
Adrien Be

50
"ไม่อะซิงโครนัส" แน่นอนสามารถเรียกว่า "ซิงโครนัส" ได้;)
Charles Wood

ในทั้งสองวิธีที่คุณแนะนำ กล่าวคือ. เรียกใช้ฟังก์ชันโดยประสบความสำเร็จจากนั้นคุณต้องเขียน ajax หลายตัวสำหรับสถานการณ์ที่แตกต่างกัน สิ่งนี้จะไม่ช่วยในการสร้างเอนจิน ajax wrapper ระดับโลก
wpcoder

ดูเหมือนว่า async: false จะเลิกใช้แล้วและการประมวลผลทั้งหมดต้องทำในฟังก์ชันเรียกกลับ
Puneet Lamba

33

มีหลายวิธีในการตอบสนอง jQuery AJAX ฉันกำลังแบ่งปันกับคุณสองแนวทางทั่วไป:

อันดับแรก:

ใช้async = falseและภายในฟังก์ชันส่งคืน ajax-object และรับการตอบสนอง 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);
});

ประการที่สอง:

ใช้ วิธี$ .extendและสร้างฟังก์ชันใหม่เช่น 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);

คุณสามารถทำให้ใหญ่เท่าที่คุณต้องการ ...


ความคิดที่ดี แต่ajaxObj['responseText']ไม่มีอยู่จริงเมื่อคุณกำหนดvar ajaxResponse
mu3

เป๊ะ !! โซลูชันแรกของคุณช่วยฉัน
Kallel Omar

วิธีที่สองคือ 100% ตกลง! ;)
Schalk Keun

7
ตั้งแต่ jQuery 1.8 การใช้ async: false เลิกใช้แล้ว!
gatteo

10

ฉันเห็นคำตอบที่นี่และแม้ว่าจะเป็นประโยชน์ แต่ก็ไม่ตรงกับที่ฉันต้องการเนื่องจากฉันต้องแก้ไขโค้ดจำนวนมาก

สิ่งที่ได้ผลสำหรับฉันกำลังทำสิ่งนี้:

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

ความหวังช่วยใครบางคน

อนาคิน


5
คุณเพิ่งปิด async
Weijing Jay Lin เมื่อ

6

แม้ว่าวิธีการทั้งหมดเกี่ยวกับการใช้งานasync: falseจะไม่ดีเนื่องจากการเลิกใช้งานและติดอยู่ในหน้าจนกว่าคำขอจะกลับมา ดังนั้นจึงมี 2 วิธีในการทำดังนี้

ขั้นที่ 1: ส่งคืนการตอบกลับ ajax ทั้งหมดในฟังก์ชันจากนั้นใช้doneฟังก์ชันเพื่อจับการตอบสนองเมื่อคำขอเสร็จสมบูรณ์ (แนะนำวิธีที่ดีที่สุด)

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

โทรหาคนดังกล่าวข้างต้น:

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

สำหรับการโทรหลายครั้งของ AJAX ให้ใช้$.when:

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

2nd: เก็บการตอบกลับไว้ในคุกกี้จากนั้นนอกการเรียก ajax จะได้รับค่าคุกกี้นั้น (ไม่แนะนำ)

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

หมายเหตุ:ใน exmple ด้านบนjquery cookiesไลบรารีจะใช้มันค่อนข้างเบาและทำงานได้เร็ว นี่คือลิงค์https://github.com/js-cookie/js-cookie


3

เพิ่มasync: falseในรายการแอตทริบิวต์ของคุณ ซึ่งจะบังคับให้เธรดจาวาสคริปต์รอจนกว่าจะดึงค่าส่งคืนก่อนที่จะดำเนินการ เห็นได้ชัดว่าคุณไม่ต้องการทำสิ่งนี้ในทุกสถานการณ์ แต่ถ้าจำเป็นต้องมีค่าก่อนดำเนินการต่อสิ่งนี้จะทำ


4
async: falseคุณไม่ควรตั้งที่เคย สิ่งนี้จะบล็อกทุกอย่างบนหน้าในช่วงเวลาของการดึงข้อมูล คุณรู้ว่า A ใน AJAX ย่อมาจากอะไร: Asynchronous คำตอบที่ถูกต้องคือ OP ต้องใช้การsuccess()โทรกลับอย่างถูกต้อง
nietonfir

2
ฉันรับทราบความจริงว่าทุกอย่างต้องรอ ภายใต้สถานการณ์บางอย่างฟังก์ชันการโทรอาจต้องการค่าที่ส่งคืนเช่นการเพิ่มเรกคอร์ดใหม่และต้องการไอดีเรกคอร์ดที่ส่งคืน เมื่อคุณรู้กฎแล้วคุณจะรู้ว่าเมื่อไรที่พวกเขาสามารถทำลายได้ อย่าพูดไม่เคย นี่คือคนอื่นที่เห็นด้วย ( stackoverflow.com/questions/3880361/… )
Hoodlum

1
@CharlesWood แต่เพียงผู้เดียวสำหรับผู้ที่ไม่สามารถเข้าใจธรรมชาติแบบ async ของ ajax ได้
nietonfir

1
@nietonfir: ถ้าคุณไม่เคยใช้async: falseทำไม jQuery ถึงใช้ตัวเลือกนี้ หากฉันไม่โหลดข้อมูลจำนวนมากไปยังเพจและจัดการกับเหตุการณ์ของผู้ใช้ก็โอเคที่จะบล็อกทุกอย่างในระยะเวลาอันสั้นสำหรับผู้ใช้รายนั้น ไม่มีอะไรผิดปกติและไม่มีอะไรเลวร้ายเกี่ยวกับมัน (หากใช้อย่างถูกต้องจะไม่บล็อกสิ่งใดเพราะในช่วงเวลานั้นจะไม่มีการดำเนินการอื่น ๆ สำหรับผู้ใช้รายนั้น)
low_rents

1
@northkildonan ไม่ใช่ไม่เป็นไร คำขอซิงค์ AJAX ไม่ดี มันบล็อกเธรดจาวาสคริปต์ที่สมบูรณ์ด้วยสิ่งที่คุณไม่สามารถควบคุมได้ คุณไม่สามารถควบคุมระยะเวลาที่อาจต้องใช้ในการดำเนินการตามคำขอ: การเชื่อมต่ออาจไม่น่าเชื่อถือเซิร์ฟเวอร์อาจใช้เวลานานกว่าที่คาดไว้เป็นต้นเหตุผลเดียวที่อยู่ใน jQuery คือคุณอาจต้องบันทึกข้อมูล ในการยกเลิกการโหลดหน้า (สถานที่เดียวที่ไม่สำคัญว่าจะใช้เวลานานกว่านี้หรือไม่เนื่องจากผู้ใช้แสดงความปรารถนาที่จะออกจากหน้านี้แล้ว) ลองดูการทดสอบหน่วย jQuery …
nietonfir

3

มันค่อนข้างเก่าและน่าเกลียดอย่าทำแบบนี้ คุณควรใช้การโทรกลับ: https://stackoverflow.com/a/5316755/591257
หากมีปัญหาเดียวกันแก้ไขด้วยวิธีนี้โดยใช้ global var. ไม่แน่ใจว่าดีที่สุด แต่ได้ผลแน่นอน เมื่อเกิดข้อผิดพลาดคุณได้รับสตริงว่าง (myVar = '') ดังนั้นคุณสามารถจัดการได้ตามต้องการ

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

4
คุณต้องเพิ่มasync: falseที่นี่ด้วยเพราะในโหมดอะซิงโครนัสไม่รับประกันว่าdataจะถูกบันทึกไว้myVarก่อนที่จะmyVarถูกส่งกลับ
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);
}

มันอาจช่วยสร้างฟังก์ชันการโทร ajax ทั่วไปและแนบฟังก์ชันที่เรียกใช้เมื่อสำเร็จการโทร ajax ดูตัวอย่าง


1

ด้วยความช่วยเหลือจากที่นี่

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

หวังว่านี่จะช่วยใครสักคนได้บ้าง


การใช้ async: false,เป็นยุคก่อนประวัติศาสตร์และเลิกใช้งานตั้งแต่ jQuery v1.8 อาจไม่มีใครช่วยได้
Alon Eitan

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.