官网:https://github.com/typicode/json-server
三步走
第一步:命令行安卓Json-server
npm install json-server
第二布:在对应文件夹下创建db.json的文件,内容如下:
{
"posts": [
{ "id": "1", "title": "a title", "views": 100 },
{ "id": "2", "title": "another title", "views": 200 }
],
"comments": [
{ "id": "1", "text": "a comment about post 1", "postId": "1" },
{ "id": "2", "text": "another comment about post 1", "postId": "1" }
],
"profile": {
"name": "typicode"
}
}
第三步:在命令行启动服务
$ npx json-server db.json
如上便启动成功
点击对应的连接我们可以得到对应的Json字符串的数据
官网:https://github.com/axios/axios
练习阶段采用链接引入方式:https://www.bootcdn.cn/axios/
通过四个按钮实现对db.json里面的数据的修改
1.发送Get请求
//第一个
btns[0].onclick = function () {
//发送AJAX请求
axios({
//请求类型
method: 'GET',
//URL
url: 'http://localhost:3000/posts/2'
}).then((responce) => {
console.log(responce);
})
}
url里的路径要写出对应的id号才能请求出对应的数据
2.添加新数据
//添加一篇新的文章
btns[1].onclick = function () {
//发送AJAX请求
axios({
//请求类型
method: 'POST',
//URL
url: 'http://localhost:3000/posts',
//设置请求体
data: {
id: '3',
titile: '祝我找到实习',
views: 999
}
}).then((responce) => {
console.log(responce);
})
}
添加新数据需要设置请求体,在里面写出要添加的数据,点击玩按钮后可以按F12在网络里看是否请求成功,再回到db.json里我们就可以看到新的数据了。
但这里有一个问题,我看视频里老师在请求体里是不用写对应的id的,但如果我不写的话,新添加的数据对应的id是一段看不懂的字符串,并不是字符串3,所以我在这里自己对数据设定了id
3.更新数据
btns[2].onclick = function () {
//发送AJAX请求
axios({
//请求类型
method: 'PUT',
//URL
url: 'http://localhost:3000/posts/3',
//设置请求体
data: {
titile: '我一定能找到实习',
views: 999999
}
}).then((responce) => {
console.log(responce);
})
}
更新数据也要在url里写出要更新的数据所对应的id号,并在请求体里写出你想修改的数据即可
4.删除数据
btns[3].onclick = function () {
//发送AJAX请求
axios({
//请求类型
method: 'delete',
//URL
url: 'http://localhost:3000/posts/3',
}).then((responce) => {
console.log(responce);
})
}
删除数据同理,删除对应id号的数据
除了像上述那样发送axios请求之外,我们还可以使用axios自带的方法来发送请求
下面用request和post来简单举个例子
//发送get请求
btns[0].onclick = function () {
axios.request(
{
method: 'GET',
url: 'http://localhost:3000/comments'
}
).then((result) => {
console.log(result);
})
}
//发送post请求
btns[1].onclick = function () {
axios.post(
//对应的url
'http://localhost:3000/comments',
//想要添加的数据
{
text: '前端之大,一锅装不下',
postId: '2'
}
).then((result) => {
console.log(result);
})
}
写法基本上和上面的基本使用区别不大
当我们发送一个axios请求的时候,其请求响应的结果如上所述,下面我们来简单分析一下里面每个属性的含义
但凡提到config这个参数的,其实指的都是配置对象,现在我们来看看里面可以设置那些内容
{
// `url` is the server URL that will be used for the request
url: '/user',
// `method` is the request method to be used when making the request
method: 'get', // default
// `baseURL` will be prepended to `url` unless `url` is absolute.
// It can be convenient to set `baseURL` for an instance of axios to pass relative URLs
// to methods of that instance.
baseURL: 'https://some-domain.com/api/',
// `transformRequest` allows changes to the request data before it is sent to the server
// This is only applicable for request methods 'PUT', 'POST', 'PATCH' and 'DELETE'
// The last function in the array must return a string or an instance of Buffer, ArrayBuffer,
// FormData or Stream
// You may modify the headers object.
transformRequest: [function (data, headers) {
// Do whatever you want to transform the data
return data;
}],
// `transformResponse` allows changes to the response data to be made before
// it is passed to then/catch
transformResponse: [function (data) {
// Do whatever you want to transform the data
return data;
}],
// `headers` are custom headers to be sent
headers: {'X-Requested-With': 'XMLHttpRequest'},
// `params` are the URL parameters to be sent with the request
// Must be a plain object or a URLSearchParams object
params: {
ID: 12345
},
// `paramsSerializer` is an optional function in charge of serializing `params`
// (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
paramsSerializer: function (params) {
return Qs.stringify(params, {arrayFormat: 'brackets'})
},
// `data` is the data to be sent as the request body
// Only applicable for request methods 'PUT', 'POST', 'DELETE , and 'PATCH'
// When no `transformRequest` is set, must be of one of the following types:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - Browser only: FormData, File, Blob
// - Node only: Stream, Buffer
data: {
firstName: 'Fred'
},
// syntax alternative to send data into the body
// method post
// only the value is sent, not the key
data: 'Country=Brasil&City=Belo Horizonte',
// `timeout` specifies the number of milliseconds before the request times out.
// If the request takes longer than `timeout`, the request will be aborted.
timeout: 1000, // default is `0` (no timeout)
// `withCredentials` indicates whether or not cross-site Access-Control requests
// should be made using credentials
withCredentials: false, // default
// `adapter` allows custom handling of requests which makes testing easier.
// Return a promise and supply a valid response (see lib/adapters/README.md).
adapter: function (config) {
/* ... */
},
// `auth` indicates that HTTP Basic auth should be used, and supplies credentials.
// This will set an `Authorization` header, overwriting any existing
// `Authorization` custom headers you have set using `headers`.
// Please note that only HTTP Basic auth is configurable through this parameter.
// For Bearer tokens and such, use `Authorization` custom headers instead.
auth: {
username: 'janedoe',
password: 's00pers3cret'
},
// `responseType` indicates the type of data that the server will respond with
// options are: 'arraybuffer', 'document', 'json', 'text', 'stream'
// browser only: 'blob'
responseType: 'json', // default
// `responseEncoding` indicates encoding to use for decoding responses (Node.js only)
// Note: Ignored for `responseType` of 'stream' or client-side requests
responseEncoding: 'utf8', // default
// `xsrfCookieName` is the name of the cookie to use as a value for xsrf token
xsrfCookieName: 'XSRF-TOKEN', // default
// `xsrfHeaderName` is the name of the http header that carries the xsrf token value
xsrfHeaderName: 'X-XSRF-TOKEN', // default
// `onUploadProgress` allows handling of progress events for uploads
// browser only
onUploadProgress: function (progressEvent) {
// Do whatever you want with the native progress event
},
// `onDownloadProgress` allows handling of progress events for downloads
// browser only
onDownloadProgress: function (progressEvent) {
// Do whatever you want with the native progress event
},
// `maxContentLength` defines the max size of the http response content in bytes allowed in node.js
maxContentLength: 2000,
// `maxBodyLength` (Node only option) defines the max size of the http request content in bytes allowed
maxBodyLength: 2000,
// `validateStatus` defines whether to resolve or reject the promise for a given
// HTTP response status code. If `validateStatus` returns `true` (or is set to `null`
// or `undefined`), the promise will be resolved; otherwise, the promise will be
// rejected.
validateStatus: function (status) {
return status >= 200 && status < 300; // default
},
// `maxRedirects` defines the maximum number of redirects to follow in node.js.
// If set to 0, no redirects will be followed.
maxRedirects: 21, // default
// `beforeRedirect` defines a function that will be called before redirect.
// Use this to adjust the request options upon redirecting,
// to inspect the latest response headers,
// or to cancel the request by throwing an error
// If maxRedirects is set to 0, `beforeRedirect` is not used.
beforeRedirect: (options, { headers }) => {
if (options.hostname === "example.com") {
options.auth = "user:password";
}
};
// `socketPath` defines a UNIX Socket to be used in node.js.
// e.g. '/var/run/docker.sock' to send requests to the docker daemon.
// Only either `socketPath` or `proxy` can be specified.
// If both are specified, `socketPath` is used.
socketPath: null, // default
// `httpAgent` and `httpsAgent` define a custom agent to be used when performing http
// and https requests, respectively, in node.js. This allows options to be added like
// `keepAlive` that are not enabled by default.
httpAgent: new http.Agent({ keepAlive: true }),
httpsAgent: new https.Agent({ keepAlive: true }),
// `proxy` defines the hostname, port, and protocol of the proxy server.
// You can also define your proxy using the conventional `http_proxy` and
// `https_proxy` environment variables. If you are using environment variables
// for your proxy configuration, you can also define a `no_proxy` environment
// variable as a comma-separated list of domains that should not be proxied.
// Use `false` to disable proxies, ignoring environment variables.
// `auth` indicates that HTTP Basic auth should be used to connect to the proxy, and
// supplies credentials.
// This will set an `Proxy-Authorization` header, overwriting any existing
// `Proxy-Authorization` custom headers you have set using `headers`.
// If the proxy server uses HTTPS, then you must set the protocol to `https`.
proxy: {
protocol: 'https',
host: '127.0.0.1',
port: 9000,
auth: {
username: 'mikeymike',
password: 'rapunz3l'
}
},
// `cancelToken` specifies a cancel token that can be used to cancel the request
// (see Cancellation section below for details)
cancelToken: new CancelToken(function (cancel) {
}),
// an alternative way to cancel Axios requests using AbortController
signal: new AbortController().signal,
// `decompress` indicates whether or not the response body should be decompressed
// automatically. If set to `true` will also remove the 'content-encoding' header
// from the responses objects of all decompressed responses
// - Node only (XHR cannot turn off decompression)
decompress: true // default
// `insecureHTTPParser` boolean.
// Indicates where to use an insecure HTTP parser that accepts invalid HTTP headers.
// This may allow interoperability with non-conformant HTTP implementations.
// Using the insecure parser should be avoided.
// see options https://nodejs.org/dist/latest-v12.x/docs/api/http.html#http_http_request_url_options_callback
// see also https://nodejs.org/en/blog/vulnerability/february-2020-security-releases/#strict-http-header-parsing-none
insecureHTTPParser: undefined // default
// transitional options for backward compatibility that may be removed in the newer versions
transitional: {
// silent JSON parsing mode
// `true` - ignore JSON parsing errors and set response.data to null if parsing failed (old behaviour)
// `false` - throw SyntaxError if JSON parsing failed (Note: responseType must be set to 'json')
silentJSONParsing: true, // default value for the current Axios version
// try to parse the response string as JSON even if `responseType` is not 'json'
forcedJSONParsing: true,
// throw ETIMEDOUT error instead of generic ECONNABORTED on request timeouts
clarifyTimeoutError: false,
},
env: {
// The FormData class to be used to automatically serialize the payload into a FormData object
FormData: window?.FormData || global?.FormData
}
}
其中有几个注意点:
axios({
url: '/post',
//post?a=100&b=200
params: {
a:100,
b:200
}
默认配置可以简单理解为我们对重复配置的统一的默认编写,后续再使用的时候就可以不用再重复配置相关的属性了
//获取按钮
const btns = document.querySelectorAll('button')
//设置默认配置
axios.defaults.method = 'GET';//设置默认的请求类型为 GET
axios.defaults.baseURL = 'http://localhost:3000'//设置基础 URL
//发送get请求
btns[0].onclick = function () {
axios({
url: '/posts',
params: {
id: 100
}
}).then((result) => {
console.log(result);
})
}
使用方法如下:
//创建实例对象
const a = axios.create({
baseURL:'http://api/a.com' //假设的一个url
timeout:2000
})
const b = axios.create({
baseURL:'http://api/b.com' //假设的一个url
timeout:2000
})
//这里的a和b与axios对象的功能几乎是一样的
那么创建实例对象有什么作用呢?
现在假设我们的项目,它的接口数据服务不是来在于单一的一个服务器,如果我们去使用默认配置去设置的话,那么我们只能实现一个服务器的接口数据,另一个又得重新配置该接口的相应的数据,这样想来也并不合适,所以这时候我们可以创建两个对象,如果我们要给a发送请求时,我们就去借助a对象来实现,同理b也一样
作用:在真正发请求前执行一个回调,做一些事情,比如追加请求头、追加参数、界面加载进度条的提示等等。一般来说只有一个回调
//请求拦截器:在发请求之前,请求拦截器可以检测到,可以在请求发出去之前做一些事情
axios.interceptors.request.use((config) => {
//config:配置对象,对象里面有一个属性很重要,headers请求头
console.log('请求拦截器执行', config);
if(Date.now() % 2 === 0) {
config.headers.token = 'zzy'; //模拟修改请求头
}
nprogress.start(); //进度条开始
return config; //检查完再把东西还给人家
});
是得到响应之后执行的一组回调函数,若请求成功,对成功的数据(成功Promise的结果值)进行处理;若请求失败,对失败进行统一的操作。
//响应拦截器
axios.interceptors.response.use(
(res) => {
console.log('响应拦截器成功的回调执行了,响应对象是:',res);
//成功的回调函数,服务器响应数据回来以后,响应拦截器可以检测到,可以做一些事情
nprogress.done(); //进度条结束
return res.data;//检查完把东西还给人家并加工一下,直接把.data给Promise结果值
},
(error) => {
console.log('响应拦截器失败的回调执行了');
alert(error);
//响应失败的回调函数,返回值和then的规则一样
//若返回非Promise则走成功的回调,返回Promise则根据状态决定
return Promise.reject(error);
});
当请求结束后,如果请求成功,就会走第一个回调,然后再走then中成功的回调,所以这里的返回值就是Promise成功的值;如果请求失败,会先走第二个失败的回调,然后根据返回值(非Promise还是Promise)决定是走then中成功的回调还是失败的回调
axios.get('http://www.zzy.com').then(res => {
console.log('请求成功',res);
}, err => {
console.log('请求失败', err);
}
一般来说,我们都会省略then的失败回调,所有的错误都在响应拦截器中捕获,做法就是在响应拦截器失败的回调中进行错误提示,并返回一个pending状态的Promise,这样的话我们使用async/await就不用包try-catch了,then也就不用指定失败的回调了。
axios.interceptors.response.use(
(res) => {
console.log('响应拦截器成功的回调执行了,响应对象是:',res);
//成功的回调函数,服务器响应数据回来以后,响应拦截器可以检测到,可以做一些事情
nprogress.done(); //进度条结束
return res.data;//检查完把东西还给人家并加工一下,直接把.data给出去
},
(error) => {
console.log('响应拦截器失败的回调执行了');
alert(error);
//响应失败的回调函数,返回值和then的规则一样
//若返回非Promise则走成功的回调,返回Promise则根据状态决定
return new Promise(()=>{});
});
......
const reqData = async () => {
//这样就不用捕获异常了,因为异常都在拦截器中捕获了。
const result = await axios.get('http://www.zzy.com');
}
加个cancelToken的这玩意儿就能取消发送中的请求;取消请求后会走失败的回调(或拦截器的失败回调)
let cancel;
发请求的按钮.onclick = () => {
if(cancel) calcel('取消了'); //用户反复点击,只发送最后一次请求
axios({
url: 'www.zzy.com',
cancelToken: new CancelToken(c => {
cancel = c; //c是一个函数,调用c就会取消请求
})
}).then(res => {
console.log('成功',res)
}, err => {
if(isCancel(err)) {
console.log('用户取消了请求',err.message);
}else {
console.log('请求失败',err);
}
});
}
关闭请求的按钮.onclick = () => {
cancel();
}
取消请求放拦截器里:
let cancel;
axios.interceptors.request.use(config => {
if(cancel) cancel('取消了');
config.cancelToken = new CancelToken(c => {
cancel = c;
})
return config;
});
axios.interceptors.response.use(res => {
return res.data;
}, err => {
if(isCancel(err)) {
console.log('用户取消了请求,原因是',err.message);
} else {
console.log('请求失败',err);
}
return new Promise(() => {});
})
发请求的按钮.onclick = async() => {
let result = await axios.get('www.zzy.com');
console.log(result);
}
留个坑,先去复习项目,学算法去了~