AJAX-lomake odottaa JSONia mutta saa HTML:ää: käy vastaus läpi vaihe vaiheelta
200-vastaus ei todista, että kyse on JSONista. Käy Verkko-paneeli läpi vaihe vaiheelta ja erota kuljetuksen, esityksen ja sopimuksen virheet.
Lomake lähetetään, latauskuvake ilmestyy ja konsoli kertoo odottamattomasta merkistä < JSONissa kohdassa 0. Sivu itsessään latautuu hyvin, ja siksi ensimmäinen vaisto on syyttää jäsentäjää tai tunnelia. Yleensä kumpikaan ei ole osallisena: lähetys on eri pyyntö kuin sivun lataus, ja se palasi jollakin, joka ei ole JSONia. Työskentele siinä järjestyksessä, jossa selain sen todella paljastaa, sillä neljä mahdollista vastausta vaatii neljä eri korjausta.
Vaihe 1: tallenna lähetys, joka todella tapahtui
Avaa Verkko-paneeli ennen lähettämistä, aseta loki säilyttämään merkinnät navigointien yli ja tee sitten yksi vaaraton testilähetys tilillä, jota sinulla on lupa käyttää. Valitse pyyntö, jonka lomake itse käynnisti, älä sivun asiakirjapyyntöä.
Varo suodattimia. XHR- tai Fetch-suodatin on kätevä, mutta jos kehys lähettää edelleen piilotetun iframen tai dynaamisesti luodun lomakkeen kautta, suodatin kätkee ainoan merkityksellisen pyynnön. Lähetä ensin kerran ilman suodatinta ja katso, mitä ilmestyi.
Kirjaa valitusta pyynnöstä kuusi asiaa ennen mitään tulkintaa: metodi, täysi URL kyselymerkkijonoineen, tila, uudelleenohjausketju, vastauksen Content-Type ja rungon ensimmäiset rivit. Chrome DevToolsin Verkko-paneelin viite kattaa näkymät Headers, Response ja Initiator, joissa ne ovat, ja muiden selainten vastaavat paneelit näyttävät samat kentät.
Vaihe 2: varmista, että kyse on siitä pyynnöstä, jota luulet
Yllättävän moni JSON-virhe on itse asiassa reititysvirhe. Jos lähetyksen käsittelijä heittää poikkeuksen ennen preventDefaultin kutsumista, selain tekee natiivin lomakkeen POSTin siihen, mitä action-attribuutti sanoo, ja palvelin vastaa kokonaisella HTML-sivulla. Käsittelijä ei koskaan suoritu, joten JSONia ei koskaan pyydetty.
Vertaa paneelin URLia siihen URLiin, jota JavaScriptisi kutsuu. Etsi uudelleenohjausta, joka päättyy muualle, puuttuvaa tai ylimääräistä lopun vinoviivaa, menetelmän epäsopua, jossa käsittelijä lähettää GETin ja päätepiste hyväksyy POSTin, tai lomaketta, joka lähettää suhteelliseen polkuun siirtyneeltä sivulta. Seuraa uudelleenohjausketju loppuun ja merkitse lopullinen URL, ei ensimmäistä.
Tarkista sitten käynnistäjä. Jos pyyntö tuli asiakirjan navigoinnista eikä skriptistäsi, olet jo löytänyt ongelman, eikä vastauksen jäsentäjän muutos auta.
Vaihe 3: luokittele tulos neljään kategoriaan
Jokainen tulos kuuluu täsmälleen yhteen näistä, ja kategoria päättää, mihin seuraavaksi katsot.
| What you see | Category | Where to look |
|---|---|---|
| Request never finishes, TLS or connection error | No usable response | Endpoint reachability, certificate, front-end timeout |
| Request completes, script gets an opaque failure | Access blocked | Cross-origin policy, credentials mode, missing response header |
| 200 with an HTML body or a login form | Wrong representation | Redirect, expired session, route fallback, error handler |
| Body begins with a notice then valid JSON | Wrong representation | Server-side warning output before serialisation |
| Valid JSON, framework rejects it | Contract mismatch | Envelope shape, field names, value types |
Keskimmäiset rivit ovat niitä, jotka ihmiset diagnosoivat väärin, koska tila on 200. Uudelleenohjauksen jälkeen saavutettu kirjautumissivu on täysin kelvollinen HTTP-vastaus ja erittäin huono JSON-asiakirja. Sisältötyyppi application/json ei korjaa sitä: se on tarra, ja väärin merkitty runko epäonnistuu silti jäsennyksessä. Pääsy estetty on rivi, joka näyttää valmiilta pyynnöltä: paneeli näyttää tilan, mutta ristiin alkuperän käytäntö pidättää rungon, joten kutsuvan skriptin kannalta se on yhtä käyttökelvoton kuin aikakatkaisu.
Neljäs rivi on yhtä yleinen vanhemmissa PHP- ja kehyspinoissa. Ennen koodattua kuormaa tulostettu vanhentumisvaroitus tuottaa rungon, jota mikään JSON-jäsentäjä ei hyväksy, ja usein se varoitus on koko selitys.
Vaihe 4: lue jäsentäjän virhe kirjaimellisesti
Virheteksti nimeää ensimmäisen merkin, joka rikkoi jäsennyksen, ja se tunnistaa kategorian yleensä ilman mitään arvailua.
| Error text (Chrome/V8) | What it means |
|---|---|
| Unexpected token < in JSON at position 0 | The body starts with markup: an HTML page or an error document |
| Unexpected end of JSON input | Empty body, or the response was truncated |
| Unexpected token o in JSON at position 1 | You parsed something already parsed, typically an object rather than text |
| Unexpected token u | The body starts with the bare word undefined, usually an empty response rendered as a string |
Tyhjä runko ja 200 on oma tapauksensa: päätepiste suoritettiin, se ei tuottanut mitään, ja jokin alempana käsitteli sitä onnistumisena. Se on sovelluksen sopimusvirhe eikä kuljetusvirhe, ja se kuuluu seuraavaan vaiheeseen, ei välityspalvelimeen. Firefox ja Safari muotoilevat samat neljä virhettä eri tavoin, joten sovita merkin tai tyhjän rungon mukaan, älä tarkan merkkijonon.
Vaihe 5: korjaa kerros, johon todisteet osoittavat
Reititysongelmassa korjaa pyyntö: korjaa action, estä käsittelijää putoamasta läpi, saa päätepiste ja metodi vastaamaan ja testaa uudelleen. Esitysongelmassa korjaa se, mikä rungon tuotti, ja selvitä, miksi virheasiakirja palautetaan sinne, missä odotettiin dataa. Sopimusongelmassa lue kehyksen todellinen odotettu rakenne käyttämällesi versiolle ja muotoile vastaus sen mukaiseksi sen sijaan, että löysäisit asiakasta.
Estetyn pääsyn vastaus tarvitsee oman kierroksensa, koska pyyntö itse voi olla oikein ja runko ei ehkä koskaan saavuta koodiasi. Vertaa vastauksen Access-Control-Allow-Originia täsmälliseen Origin-otsakkeeseen, jonka selain lähetti, ja muista, että jokerimerkki ei täytä valtuutettua pyyntöä. Yhdistä asiakkaassa credentials: 'include' palvelimella Access-Control-Allow-Credentials: true kanssa ja tarkista, käyttikö kutsu tilaa no-cors, jossa läpinäkymätön runko on dokumentoitu tulos eikä vika.
Jäsentäjän korvaaminen sallivammalla on ainoa korjaus, jota pitää välttää. Vastauksen arvioiminen koodina tai tekstin kuoriminen, kunnes se jäsentyy, kätkee sopimusepäsovun ja lisää injektiopinnan vaihdossa hiljaisuuteen. Samoin tilan tarkistaminen erillään rungosta on välttämätöntä: 200, joka kantaa sovellustason virheobjektia, on monissa APIissa normaali ja se on käsiteltävä lukemalla kuorma.
Kun tarvitset apua joltakulta muulta, jaa minimaalinen tietue — metodi, URL, tila, lopullinen URL uudelleenohjausten jälkeen, vastauksen sisältötyyppi, rungon muoto ja odotettu sopimus — älä raakaa vientiä. Verkkoarkistot sisältävät evästeitä, tokeneita, kyselymerkkijonoja ja lomakkeessa olleet henkilötiedot, eikä automaattinen puhdistaja ole katselmus.
- Tallenna pyyntö ilman suodatinta ennen kuin muutat mitään koodia.
- Varmista, että käynnistäjä oli skriptisi ja lopullinen URL on päätepisteesi.
- Luokittele vastaus ennen kuin kosket jäsentäjään.
- Korjaa reititys, pääsy, esitys tai sopimus, ja ei koskaan jäsentäjää löysäämällä.