jQuery - Niedozwolone wywołanie

108

jQuery v1.7.2

Mam tę funkcję, która powoduje następujący błąd podczas wykonywania:

Uncaught TypeError: Illegal invocation

Oto funkcja:

$('form[name="twp-tool-distance-form"]').on('submit', function(e) {
    e.preventDefault();

    var from = $('form[name="twp-tool-distance-form"] input[name="from"]');
    var to = $('form[name="twp-tool-distance-form"] input[name="to"]');
    var unit = $('form[name="twp-tool-distance-form"] input[name="unit"]');
    var speed = game.unit.speed($(unit).val());

    if (!/^\d{3}\|\d{3}$/.test($(from).val()))
    {
        $(from).css('border-color', 'red');
        return false;
    }

    if (!/^\d{3}\|\d{3}$/.test($(to).val()))
    {
        $(to).css('border-color', 'red');
        return false;
    }

    var data = {
        from : from,
        to : to,
        speed : speed
    };

    $.ajax({
        url : base_url+'index.php',
        type: 'POST',
        dataType: 'json',
        data: data,
        cache : false
    }).done(function(response) {
        alert(response);
    });

    return false;
});

Jeśli usunę dataz wywołania Ajax, to działa .. jakieś sugestie?

Dzięki!

yoda
źródło
spróbuj usunąć fromz danych. Może jest to sprzeczne z jquery z
gopi1410,
6
Zdajesz sobie sprawę, że próbujesz przekazać obiekty jQuery, a nie JSON, prawda?
asawyer
18
Zdarza mi się regularnie, kiedy zapomnę .val () na jakimś obiekcie jQuery ...
userfuser

Odpowiedzi:

118

Myślę, że musisz mieć ciągi jako wartości danych. Prawdopodobnie jest to coś wewnętrznie w jQuery, co nie koduje / serializuje poprawnie obiektów To i From.

Próbować:

var data = {
    from : from.val(),
    to : to.val(),
    speed : speed
};

Zauważ również na liniach:

$(from).css(...
$(to).css(

Nie potrzebujesz opakowania jQuery, ponieważ Do i Od są już obiektami jQuery.

LessQuesar
źródło
2
Dzięki, zapomniałem, że ładowałem obiekty zamiast łańcuchów, zwykle ładuję łańcuchy :)
yoda
3
Takie podejście mi pomaga. Nazywam swoje zmienne jako $from = $('#from');To pomaga mi zapamiętać, że reprezentuje obiekt jQuery, co pomaga uniknąć wywoływania metody na czymś, co jest ciągiem znaków lub próbach manipulowania łańcuchem .toString()lub czymś, gdy jest to obiekt jQuery.
timbrown
.val()Brakowało mi części, więc nie przekazywała wartości.
SharpC
109

Spróbuj ustawić processData: false w ustawieniach Ajax, takich jak to

$.ajax({
    url : base_url+'index.php',
    type: 'POST',
    dataType: 'json',
    data: data,
    cache : false,
    processData: false
}).done(function(response) {
    alert(response);
});
Justo
źródło
8
By default, data passed in to the data option as an object (technically, anything other than a string) will be processed and transformed into a query string, fitting to the default content-type "application/x-www-form-urlencoded". If you want to send a DOMDocument, or other non-processed data, set this option to false.
BOTJr.
Konieczne może być również dodanie contentType: false. Zrobiłem podczas przesyłania pliku. Zobacz stackoverflow.com/questions/21044798/…
khylo
18

Dla przypomnienia może się to również zdarzyć, jeśli spróbujesz użyć niezadeklarowanej zmiennej w danych, takich jak

var layout = {};
$.ajax({
  ...
  data: {
    layout: laoyut // notice misspelled variable name
  },
  ...
});
Ivan Ivanić
źródło
1
Dziękuję za to!! To było miejsce, w którym byłem blokowany.
Matt Zelenak
13

Jeśli chcesz przesłać formularz przy pomocy Javascript FormData API z wgrywaniem plików musisz ustawić poniżej dwie opcje:

processData: false,
contentType: false

Możesz spróbować w następujący sposób:

//Ajax Form Submission
$(document).on("click", ".afs", function (e) {
    e.preventDefault();
    e.stopPropagation();
    var thisBtn = $(this);
    var thisForm = thisBtn.closest("form");
    var formData = new FormData(thisForm[0]);
    //var formData = thisForm.serializeArray();

    $.ajax({
        type: "POST",
        url: "<?=base_url();?>assignment/createAssignment",
        data: formData,
        processData: false,
        contentType: false,
        success:function(data){
            if(data=='yes')
            {
                alert('Success! Record inserted successfully');
            }
            else if(data=='no')
            {
                alert('Error! Record not inserted successfully')
            }
            else
            {
                alert('Error! Try again');
            }
        }
    });
});
Bablu Ahmed
źródło
Co robią te dwie opcje, czy możesz wyjaśnić?
rahim.nagori
2

W moim przypadku po prostu się zmieniłem

Uwaga: tak jest w przypadku Django, więc dodałem csrftoken. W twoim przypadku możesz go nie potrzebować.

Dodano contentType: false,processData: false

Skomentowane "Content-Type": "application/json"

$.ajax({
    url: location.pathname, 
    type: "POST",
    crossDomain: true,
    dataType: "json",
    headers: {
        "X-CSRFToken": csrftoken,
        "Content-Type": "application/json"
    },
    data:formData,
    success: (response, textStatus, jQxhr) => {

    },
    error: (jQxhr, textStatus, errorThrown) => {

    }
})

do

$.ajax({
    url: location.pathname, 
    type: "POST",
    crossDomain: true,
    dataType: "json",
    contentType: false,
    processData: false,
    headers: {
        "X-CSRFToken": csrftoken
        // "Content-Type": "application/json",
    },
    data:formData,
    success: (response, textStatus, jQxhr) => {

    },
    error: (jQxhr, textStatus, errorThrown) => {

    }
})

i zadziałało.

kadłub
źródło
2

W moim przypadku nie zdefiniowałem wszystkich zmiennych, które przekazuję do danych w Ajax.

var page = 1;

$.ajax({
    url: 'your_url',
    type: "post",
    data: { 'page' : page, 'search_candidate' : search_candidate }
    success: function(result){
        alert('function called');
    }
)}

Właśnie zdefiniowałem zmienną var search_candidate = "candidate name";i jej działanie.

var page = 1;
var search_candidate = "candidate name"; // defined
$.ajax({
    url: 'your_url',
    type: "post",
    data: { 'page' : page, 'search_candidate' : search_candidate }
    success: function(result){
        alert('function called');
    }
)}
Rajesh Kharatmol
źródło
0

Mój problem nie był związany processData. Było tak, ponieważ wysłałem funkcję, której nie można później wywołać, applyponieważ nie ma wystarczającej liczby argumentów. W szczególności nie powinienem był używać alertjako erroroddzwaniania.

$.ajax({
    url: csvApi,
    success: parseCsvs,
    dataType: "json",
    timeout: 5000,
    processData: false,
    error: alert
});

Zobacz tę odpowiedź, aby uzyskać więcej informacji na temat tego, dlaczego może to być problem: Dlaczego niektóre wywołania funkcji są określane w JavaScript jako „nielegalne wywołania”?

Sposób, w jaki mogłem to odkryć, polegał na dodaniu a console.log(list[ firingIndex ])do jQuery, aby móc śledzić, co uruchamia.

To była poprawka:

function myError(jqx, textStatus, errStr) {
    alert(errStr);
}

$.ajax({
    url: csvApi,
    success: parseCsvs,
    dataType: "json",
    timeout: 5000,
    error: myError // Note that passing `alert` instead can cause a "jquery.js:3189 Uncaught TypeError: Illegal invocation" sometimes
});
ubershmekel
źródło
0

W moim przypadku (używając webpacka 4) w ramach anonimowej funkcji, której używałem jako callback.

Musiałem użyć window.$.ajax()zamiast $.ajax()pomimo:

import $ from 'jquery';
window.$ = window.jQuery = $;
Zanderwar
źródło
0

Jest to również przyczyna: jeśli zbudowałeś kolekcję jQuery (przez .map () lub coś podobnego), nie powinieneś używać tej kolekcji w danych .ajax (). Ponieważ nadal jest to obiekt jQuery , a nie zwykły JavaScript Array . Powinieneś użyć .get () na i, aby uzyskać zwykłą tablicę js i powinieneś użyć jej w ustawieniach danych w .ajax ().

Burak TARHANLI
źródło