简介:fetch api 是一种ajax新规范,用来取代XMLHttpRequest
优点:1 接口合理化,将不同的性质分散在不同的对象上; 2 操作返回使用Promise对象,避免了嵌套的回调函数
缺点: 浏览器的支持不是很好
使用:
getting data 示例:
fetch('https://api.github.com/users/chriscoyier/repos') .then(response => console.log(response))
返回结果:
请求的数据其实隐藏在body,作为ReadableStream, 需要采用合适的方法将其转换成我们可以读取的数据
因为,该请求返回的数据是json格式的,所以使用response.json()来转换,下面列出了其他的一些转换方式
比如,图片使用response.blob(), XML文件使用response.text()
详见:https://developer.mozilla.org/en-US/docs/Web/API/Response
下面,使用response.json()解析返回值, Wow! 终于看到数据了!
fetch('https://api.github.com/users/chriscoyier/repos') .then(response => response.json()) .then(data => { console.log(data) })
返回的结果
sending data 示例:
fetch('some-url', options)
- first option: request method 可以使用 post put , delete , 或 post (默认)
- second option: headers 如果传送的数据是json格式的,需要设置 Content-Type 为 application/json
- third option: 如果body要传送的数据是json, 需要使用JSON.stringify()进行转换
fetch('https://www.jamapi.xyz', { method: 'post', headers: { 'Accept': 'application/json', 'Content-type': 'application/json' }, body: JSON.stringify({ url: 'http://cssvalues.com', json_data: '{"values": "#' + prop + ' ul"}' })}).then(function (response) { return response.json();}).then(function (json) { if (!json.error) { console.log(json.values.replace(/\s\s+/g, ', ')); } else { console.log('Please enter a valid CSS property'); }});
错误处理:
- 请求的资源不存在
fetch('https://api.github.com/users/chrissycoyier/repos') .then(response => response.json()) .then(data => console.log('data is', data)) .catch(error => console.log('error is', error));
会发现,没有走catch, 还是走了第二个then, 这说明fetch不在乎请求是否成功,只关心发送请求和从服务端接收数据,因此,第一个then需要改造一下,需要检测response 是否 ok
fetch('some-url') .then(response => { if (response.ok) { return response.json() } else { // Find some way to get to execute .catch() } });
有两种激活catch的方法, throw Error 或 reject Promise
// throwing an Errorelse { throw new Error('something went wrong!')}// rejecting a Promiseelse { return Promise.reject('something went wrong!')}
来看一下标准的包含错误处理的代码:
fetch('https://api.github.com/users/chrissycoyier/repos') .then(response => { if (response.ok) { return response.json() } else { return Promise.reject('something went wrong!') } }) .then(data => console.log('data is', data)) .catch(error => console.log('error is', error));
再看结果, 触发了catch
但是错到底是什么,用户可能都不知道,需要告诉用户错误状态和错误信息
fetch('https://api.github.com/users/chrissycoyier/repos') .then(response => { if (response.ok) { return response.json() } else { return Promise.reject({ status: response.status, statusText: response.statusText }) } }) .then(data => console.log('data is', data)) .catch(error => { if (error.status === 404) { // do something about 404 } });
将返回的数据和错误状态一并封装, 先读取response.json,再决定怎么做
fetch('https://api.github.com/users/chrissycoyier/repos') .then(handleResponse) .then(data => console.log(data)) .catch(error => console.log(error))function handleResponse(response) { return response.json() .then(json => { if (response.ok) { return json } else { let error = Object.assign({}, json, { status: response.status, statusText: response.statusText }) return Promise.reject(error) } })}
- 处理其他类型的response
fetch('https://api.github.com/users/chrissycoyier/repos') .then(handleResponse) .then(data => console.log(data)) .catch(error => console.log(error))function handleResponse(response) { let contentType = response.headers.get('content-type') if (contentType.includes('application/json')) { return handleJSONResponse(response) } else if (contentType.includes('text/html')) { return handleTextResponse(response) } else { throw new Error(`Sorry, content-type ${contentType} not supported`) }}function handleJSONResponse (response) { return response.json() .then(json => { if (response.ok) { return json } else { return Promise.reject(Object.assign({}, json, { status: response.status, statusText: response.statusText })) } })}function handleTextResponse (response) { return response.text() .then(text => { if (response.ok) { return text } else { return Promise.reject({ status: response.status, statusText: response.statusText, err: text }) } })}
参考资料:
http://javascript.ruanyifeng.com/bom/ajax.html
https://css-tricks.com/using-fetch/