feat: improve `$` helpers and error object (#113)

* test: add error fixture

* feat: improve `$` helpers and error object

* chore: remove duplicated line

* docs: clear error properies

* docs: improvements

Co-authored-by: Sébastien Chopin <seb@nuxtjs.com>
master
pooya parsa 2020-06-17 13:01:35 +02:00 committed by GitHub
parent 6fdc49f50c
commit ada73879f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 63 additions and 5 deletions

View File

@ -18,6 +18,13 @@ See [here](/guide/advanced.html#hooks) for usage.
- arguments: `(error)`
If the error originated from a request, the property `err.response` might be available.
If the error originated from a request.
Available properties:
- `error.statusCode` (may be undefined)
- `error.response?.data`(may be undefined)
You can optionally return a value or promise that can resolve for fallback response. If hook returns any value, other hooks **won't** be called.
See [here](/guide/advanced.html#hooks) for usage.

View File

@ -42,9 +42,12 @@ export default function ({ $http }) {
})
$http.onError(error => {
if(error.response.status === 500) {
if (error.statusCode === 500) {
alert('Request Error!')
}
// Tip: error.response will be undefined if the connection dropped to the server
// Tip: You can use error.response.data to get response message
// Tip: You can return an object or Promise as fallback response to avoid rejection
})
}
```

View File

@ -23,7 +23,7 @@ const res = await $http.get('https://unpkg.com/nuxt/package.json')
const data = await res.json()
```
Alternatively for json only you can use `$` prefixed shortcut:
Alternatively for json only you can use `$` prefixed shortcut that smartly parses response using [destr](https://github.com/nuxt-contrib/destr).
```js
await $http.$get('https://unpkg.com/nuxt/package.json')

View File

@ -1,4 +1,5 @@
import defu from 'defu'
import destr from 'destr'
const KY = process.server ? require('ky-universal/node') : require('ky-universal/browser').default
@ -91,17 +92,33 @@ for (let method of ['get', 'head', 'delete', 'post', 'put', 'patch']) {
const response = await this._ky[method](url, _options)
return response
} catch (error) {
// Try to fill error with useful data
if (error.response) {
error.statusCode = error.response.status
try {
error.response.data = destr(await error.response.text())
} catch (_) { }
}
// Call onError hook
if (_options.hooks.onError) {
_options.hooks.onError.forEach(fn => fn(error))
for (const fn of _options.hooks.onError) {
const res = fn(error)
if (res !== undefined) {
return res
}
}
}
// Throw error
throw error
}
}
HTTP.prototype['$' + method] = function (url, arg1, arg2) {
return this[method](url, arg1, arg2).then(res => res.json())
return this[method](url, arg1, arg2)
.then(response => (response && response.text) ? response.text() : response)
.then(body => destr(body))
}
}

View File

@ -1,6 +1,11 @@
module.exports = {
path: '/test_api',
handler (req, res) {
if (req.url === '/error') {
res.statusCode = 418
res.end('Detailed error message')
}
res.end(JSON.stringify({
url: req.url,
method: req.method

View File

@ -0,0 +1,14 @@
<template>
<div>
Response: {{ res }}
</div>
</template>
<script>
export default {
async asyncData ({ app }) {
const res = await app.$http.$get('error')
return { res }
}
}
</script>

View File

@ -5,4 +5,11 @@ export default function ({ $http, redirect }) {
// eslint-disable-next-line no-console
console.log('Request:', JSON.stringify(options))
})
$http.onError((err) => {
return {
statusCode: err.statusCode,
message: err.response ? err.response.data : err.message
}
})
}

View File

@ -36,6 +36,11 @@ describe('module', () => {
expect(defaults.headers.xsrfHeaderName).toBe('X-CSRF-TOKEN')
})
test('error', async () => {
const html = await fetch(url('/error')).then(r => r.text())
expect(html).toMatch('res:{statusCode:418,message:"Detailed error message"}')
})
test('ssr', async () => {
const makeReq = login => fetch(url('/ssr' + (login ? '?login' : '')))
.then(r => r.text())