Un article de Baldur Bjarnason explique comment utiliser
FormData pour sérialiser les données qui proviennent d’un
formulaire, soit pour du classique urlencoded soit pour du JSON.
constformdata=newFormData(form)fetch('/test/thing',{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded',},body:newURLSearchParams(formdata).toString(),}).then((result)=>{// do something}).catch((err)=>{// fix something.})
constformdata=newFormData(form)fetch('/test/thing',{method:'POST',headers:{'Content-Type':'application/json',},body:JSON.stringify(Object.fromEntries(formdata.entries())),}).then((result)=>{// do something}).catch((err)=>{// fix something.})
Vérifier la nature de la réponse d’erreur d’une API⚓︎
2022-08
Une astuce de Chris Ferdinandi pour évaluer la bonne erreur à
afficher lorsqu’elle provient d’une API, on utilise le header de
content-type pour déterminer la méthode à appeler sur l’erreur.
fetch('https://jsonplaceholder.typicode.com/tododos').then(function(response){if(response.ok){returnresponse.json()}throwresponse}).then(function(data){console.log(data)}).catch(function(error){// Check if the response is JSON or notletisJSON=error.headers.get('content-type').includes('application/json')// If JSON, use text(). Otherwise, use json().letgetMsg=isJSON?error.json():error.text()// Warn the error and message when it resolvesgetMsg.then(function(msg){console.warn(error,msg)})})
functionrequest(url,options=undefined){returnfetch(url,optionsHandler(options)).then(handleResponse).catch((error)=>{conste=newError(`${error.message}${url}`)Object.assign(e,error,{url})throwe})}functionoptionsHandler(options){constdef={method:'GET',headers:{'Content-Type':'application/json'},}if(!options)returndefletr=Object.assign({},def,options)// Deal with body, can be either a hash or a FormData,// will generate a JSON string from it if in options.deleter.bodyif(options.body){// Allow to pass an empty hash too.if(!(Object.getOwnPropertyNames(options.body).length===0)){r.body=JSON.stringify(options.body)}elseif(options.bodyinstanceofFormData){r.body=JSON.stringify(Array.from(options.body.entries()))}}returnr}consthandlers={JSONResponseHandler(response){returnresponse.json().then((json)=>{if(response.ok){returnjson}else{returnPromise.reject(Object.assign({},json,{status:response.status,}))}})},textResponseHandler(response){if(response.ok){returnresponse.text()}else{returnPromise.reject(Object.assign({},{status:response.status,message:response.statusText,}))}},}functionhandleResponse(response){letcontentType=response.headers.get('content-type')if(contentType.includes('application/json')){returnhandlers.JSONResponseHandler(response)}elseif(contentType.includes('text/html')){returnhandlers.textResponseHandler(response)}else{thrownewError(` Sorry, content-type '${contentType}' is not supported, only 'application/json' and 'text/html' are. `)}}
En entrée, on redéfinit le body de notre requête en fonction de sa
nature (détectée automagiquement). En sortie, on regarde le content-type
pour appliquer le handler approprié.
classServerErrorextendsError{}functionrequest(url,options){returnfetch(url,options).then((response)=>[response,response.json()]).then(([response,data])=>{if(response.ok){returndata}else{conste=newServerError(`${url}${response.status}${data}`)e.status=response.statuse.url=urle.data=datathrowe}}).catch((error)=>{if(errorinstanceofServerError)throwerrorconste=newError(`${error.message}${url}`)e.url=urlthrowe})}functionhandleError(error){console.error(error)consterrorURL=newwindow.URL(error.url)constuserMessage=` Le domaine ${errorURL.host} semble être inaccessible. Nous en avons été informés, veuillez réessayer plus tard. `}