1. 传统形式的URL
2. Restful形式的URL
// 三者的顺序不确定
$.ajax({
url:'http://localhost:3000/data',
success:function(data){
console.log(data)
}
});
$.ajax({
url:'http://localhost:3000/data1',
success:function(data){
console.log(data)
}
});
$.ajax({
url:'http://localhost:3000/data2',
success:function(data){
console.log(data)
}
});
② 异步调用结果如果存在依赖需要嵌套(出现回调地狱)
$.ajax({
url:'http://localhost:3000/data',
success:function(data){
console.log(data)
$.ajax({
url:'http://localhost:3000/data1',
success:function(data){
console.log(data)
$.ajax({
url:'http://localhost:3000/data2',
success:function(data){
console.log(data)
}
});
}
});
}
});
Promise是异步编程的一种解决方案,从语法上讲, Promise是一个对象,从它可以获取异步操作的消息。
使用 Promise主要有以下好处:
官方文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
p.then
获取处理结果var p = new Promise(function(resolve,reject){
// 成功时调用 resolve()
resolve(data)
// 失败时调用 reject()
reject(err)
});
p.then(function(data){
// 从resolve得到正常结果,data为resolve中的参数
},function(err){
// 从reject得到错误信息,err为reject中的参数
});
补充:Promise的链式调用
new Promise((resolve,reject)=>{
// 模拟网络请求
setTimeout(()=>{
resolve('aaa')
},1000)
}).then(res=>{
console.log(res); //aaa
return new Promise(resolve=>{
resolve('bbb')
})
}).then(res=>{
console.log(res); //bbb
return new Promise(resolve=>{
resolve('ccc')
})
}).then(res=>{
console.log(res) //ccc
})
new Promise((resolve,reject)=>{
// 模拟网络请求
setTimeout(()=>{
resolve('aaa')
},1000)
}).then(res=>{
console.log(res); //aaa
return Promise.resolve('bbb')
}).then(res=>{
console.log(res); //bbb
return Promise.resolve('ccc')
}).then(res=>{
console.log(res) //ccc
})
new Promise((resolve,reject)=>{
// 模拟网络请求
setTimeout(()=>{
resolve('aaa')
},1000)
}).then(res=>{
console.log(res) // aaa
return Promise.reject('error message')
// 上面这句话也可以这样调用
// throw 'error message'
}).then(res=>{
console.log(res) // 这句话不执行
}).catch(err=>{
console.log(err) // error message
})
1. 处理原生Ajax
function queryData(url){
var p = new Promise(function(resolve,reject){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState != 4) return;
if(xhr.readyState == 4 && xhr.status == 200){
// 处理正常情况
resolve(xhr.responseText)
}else{
// 处理异常情况
reject('服务器错误')
}
};
xhr.open('get',url)
xhr.send(null)
});
return p
}
queryData('http://localhost:3000/data')
.then(function(data){
console.log(data)
},function(info){
console.log(info)
});
2. 发送多次Ajax请求
queryData('http://localhost:3000/data')
.then(function(data){
console.log(data)
return queryData('http://localhost:3000/data1')
})
.then(function(data){
console.log(data)
return queryData('http://localhost:3000/data2')
})
.then(function(data){
console.log(data)
});
function queryData(url){
return new Promise(function(resolve,reject){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState != 4) return;
if(xhr.readyState == 4 && xhr.status == 200){
// 处理正常情况
resolve(xhr.responseText)
}else{
// 处理异常情况
reject('服务器错误')
}
};
xhr.open('get',url)
xhr.send(null)
});
}
queryData('http://localhost:3000/data')
.then(function(data){
return queryData('http://localhost:3000/data1')
})
.then(function(data){
return new Promise(function(resolve,reject){
setTimeout(function(){
resolve(123)
},1000)
})
})
.then(function(data){
// 1
console.log(data) // 123
// 2 产生一个默认的promise实例对象
return 'hello'
})
.then(function(data){
console.log(data) // hello
});
1. 实例方法
function foo(){
return new Promise(function(resolve,reject){
setTimeout(function(){
resolve(123)
// reject('error')
},100)
})
}
foo()
.then(function(data){
console.log(data) // 正常时执行 123
})
.catch(function(data){
console.log(data) // 异常时执行 error
})
.finally(function(){
console.log('finished') // 无论正常、异常都执行
})
function queryData(url){
return new Promise(function(resolve,reject){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState != 4) return;
if(xhr.readyState == 4 && xhr.status == 200){
// 处理正常情况
resolve(xhr.responseText)
}else{
// 处理异常情况
reject('服务器错误')
}
};
xhr.open('get',url)
xhr.send(null)
});
}
var p1 = queryData('http://localhost:3000/a1')
var p2 = queryData('http://localhost:3000/a2')
var p3 = queryData('http://localhost:3000/a3')
Promise.all([p1,p2,p3]).then(function(result){
console.log(result)
}) // 返回后台全部结果
Promise.race([p1,p2,p3]).then(function(result){
console.log(result)
}) // 返回第一个返回的结果
1. 基本特征
2. 语法结构
fetch(url)
.then(fn2)
.then(fn3)
...
.catch(fn)
官方文档:https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
fetch('/abc').then(data => {
return data.text() // 返回一个Promise实例对象
}).then(ret=>{
// 注意这里得到的才是最终的数据
console.log(ret)
})
text()方法属于fetchAPI的一部分,它返回一个Promise实例对象,用于获取后台返回的数据
1. 常用配置选项
fetch('/abc',{
method:'GET'
}).then(data => {
return data.text() // 返回一个Promise实例对象
}).then(ret=>{
// 注意这里得到的才是最终的数据
console.log(ret)
})
2. GET请求方式的参数传递
方式1:
// client发送,从server端返回
fetch('/abc?id=123',{
method:'GET'
}).then(data => {
return data.text() // 返回一个Promise实例对象
}).then(ret=>{
console.log(ret)
})
// server接收,并发送给client
app.get('/abc',(req,res)=>{
res.send('传统的URL传递参数!' + req.query.id)
})
方式2:
// client发送,从server端返回
fetch('/abc/123',{
method:'GET'
}).then(data => {
return data.text() // 返回一个Promise实例对象
}).then(ret=>{
console.log(ret)
})
// server接收,并发送给client
app.get('/abc/:id',(req,res)=>{
res.send('Restful形式的URL传递参数!' + req.params.id)
})
3. DELETE请求方式的参数传递
// client发送,从server端返回
fetch('/abc/123',{
method:'DELETE'
}).then(data => {
return data.text() // 返回一个Promise实例对象
}).then(ret=>{
console.log(ret)
})
// server接收,并发送给client
app.delete('/abc/:id',(req,res)=>{
res.send('DELETE请求传递参数!' + req.params.id)
})
4. POST请求方式的参数传递
方式1(普通传参):
// client发送,从server端返回
fetch('/abc',{
method:'POST',
body:'uname=lisi&pwd=123',
headers:{
'Content-Type':'application/x-www-form-urlencoded'
}
}).then(data => {
return data.text() // 返回一个Promise实例对象
}).then(ret=>{
console.log(ret)
})
const bodyParser = require('body-parser')
// server接收,并发送给client
app.post('/abc',(req,res)=>{
res.send('POST请求传递参数!' + req.body.uname + '----' + req.body.pwd)
})
方式2(JSON传参):
// client发送,从server端返回
fetch('/abc',{
method:'POST',
body:JSON.stringify({
uname: 'lisi',
age:12
}),
headers:{
'Content-Type':'application/json'
}
}).then(data => {
return data.text() // 返回一个Promise实例对象
}).then(ret=>{
console.log(ret)
})
const bodyParser = require('body-parser')
const app = express()
app.use(bodyParser.json())
// server接收,并发送给client
app.post('/abc',(req,res)=>{
res.send('POST请求传递参数!' + req.body.uname + '----' + req.body.pwd)
})
5. PUT请求方式的参数传递
// client发送,从server端返回
fetch('/abc/123',{
method:'PUT',
body:JSON.stringify({
uname: 'lisi',
age:12
}),
headers:{
'Content-Type':'application/json'
}
}).then(data => {
return data.text() // 返回一个Promise实例对象
}).then(ret=>{
console.log(ret)
})
const bodyParser = require('body-parser')
const app = express()
app.use(bodyParser.json())
// server接收,并发送给client
app.put('/abc/:id',(req,res)=>{
res.send('PUT请求传递参数!' + req.params.id + '----' + req.body.uname + '----' + req.body.pwd)
})
响应数据格式
// client发送,从server端返回
fetch('/abc').then(data => {
// return data.text()
return data.json()
}).then(data=>{
console.log(data) // JSON对象
console.log(data.uname) // JSON对象.属性
})
// server接收,并发送给client
app.get('/abc',(req,res)=>{
res.json({
uname: 'lisi',
age: 13,
gender: 'male'
})
})
附:字符串转JSON方法——var obj = JSON.parse(str)
axios(官网:https://github.com/axios/axios)是一个基于Promise用于浏览器和node.js的HTTP客户端。
它具有以下特征:
项目安装Axios:
cnpm install axios --save
基本使用:
axios({
url:'/adata',
method:'GET' // 默认GET方法
}).then(ret=>{
// data 属性名称是固定的,用于获取后台响应的实际数据
console.log(ret.data)
})
注:axios发送并发请求
// axios发送并发请求,两个请求同时相应之后才有结果
axios.all([axios({
url:'/home/data1'
}), axios({
url:'/home/data2'
})]).then(results=>{
console.log(results) // 返回一个数组[res1,res2]
})
spread:
axios.all([axios({
url:'/home/data1'
}), axios({
url:'/home/data2'
})]).then(axios.spread((res1,res2) => {
console.log(res1) // res1
console.log(res2) // res2
}))
1. GET传递参数
方法1:
axios.get('/adata?id=123')
.then(ret=>{
console.log(ret.data) // axios get 传递参数123
})
// server接收,并发送给client
app.get('/adata',(req,res)=>{
res.send('axios get 传递参数' + req.query.id)
})
方法2:
axios.get('/adata/123')
.then(ret=>{
console.log(ret.data) // axios get (Restful) 传递参数123
})
// server接收,并发送给client
app.get('/adata/:id',(req,res)=>{
res.send('axios get (Restful) 传递参数' + req.params.id)
})
axios.get('/adata',{
params:{
id:123
}
})
.then(ret=>{
console.log(ret.data) // axios get 传递参数123
})
// server接收,并发送给client
app.get('/adata',(req,res)=>{
res.send('axios get 传递参数' + req.query.id)
})
2. DELETE传递参数
方法1:
axios.delete('/adata?id=123')
.then(ret=>{
console.log(ret.data)
})
方法2:
axios.delete('/adata/123')
.then(ret=>{
console.log(ret.data)
})
方法3:
axios.delete('/adata',{
params:{
id:123
}
})
.then(ret=>{
console.log(ret.data)
})
3. POST传递参数
axios.post('/adata',{
uname:'tom',
pwd:123
}).then(ret=>{
console.log(ret.data)
})
// server接收,并发送给client
app.post('/adata',(req,res)=>{
res.send('axios post 传递参数' + req.body.uname + req.body.pwd)
})
const params = new URLSearchParams();
params.append('uname','zhangsan');
params.append('pwd','111');
axios.post('/adata',params).then(ret=>{
console.log(ret.data)
})
// server接收,并发送给client
app.post('/adata',(req,res)=>{
res.send('axios post 传递参数' + req.body.uname + req.body.pwd)
})
4. PUT传递参数
axios.put('/adata/123',{
uname:'tom',
pwd:123
}).then(ret=>{
console.log(ret.data)
})
// server接收,并发送给client
app.put('/adata/:id',(req,res)=>{
res.send('axios post 传递参数' + req.params.id + req.body.uname + req.body.pwd)
})
响应结果的主要属性
data为例:
axios.get('/adata')
.then(ret=>{
console.log(ret.data.uname) // lisi
})
// server接收,并发送给client
app.post('/adata',(req,res)=>{
res.json({
uname:'lisi',
age:12
});
})
axios.defaults.timeout = 3000
// 超时时间axios.defaults.baseURL = 'http://localhost:3000/app'
// 默认地址axios.defaults.headers[' mytoken'] = 'aqwerwqwerqwere2ewe23eresdf23'
// 设置请求头配置请求的基准URL地址(默认地址):
axios.defaults.baseURL = 'http://localhost:3000/'
axios.get('adata') // 拼接成:http://localhost:3000/adata
.then(ret=>{
console.log(ret.data.uname) // lisi
})
配置请求头信息:
axios.defaults.headers[' mytoken'] = 'aqwerwqwerqwere2ewe23eresdf23'
const instance1 = axios.create({
baseURL: 'http://192.168.0.1:8000',
timeout:5000
})
const instance2 = axios.create({
baseURL: 'http://192.168.0.2:8000',
timeout:8000
})
instance1({
url:'/home/data1'
}).then(res=>{
console.log(res)
})
1. 请求拦截器
在请求发出之前设置一些信息,一般包括如下情况:
axios.interceptors.request.use(function(config){
// 在请求发出之前进行一些信息设置
config.headers.mytoken = 'nihao';
return config
},function(err){
// 处理响应的错误信息
console.log(err)
})
// axios.get().then...
2. 响应拦截器
axios.interceptors.response.use(function(res){
// 在这里对返回的数据进行处理
var data = res.data
return data
},function(err){
// 处理响应的错误信息
console.log(err)
})
// axios.get().then...
对于不同组件调用axios时,需要在每个组件中引入axios的配置信息,一旦发生改变需要在每个组件中修改,非常麻烦。
因此最好的方式是引入一个全局Axios配置文件,并将公共部分封装起来,其他组件使用使直接引入即可。需要修改时(比如baseURL等信息),只需要修改这个全局配置文件即可,无需在每个组件中进行修改。
在src下新建一个名为network
的文件夹,并在文件夹内新建一个名为request.js
配置文件
request.js:
import axios from 'axios'
export function request(config) {
// 1.创建axios实例
const instance = axios.create({
baseURL: 'http://192.168.0.1',
timeout: 5000
})
// 2. axios的拦截器
// 2.1 请求拦截器
instance.interceptors.request.use(config => {
// console.log(config); // 拦截请求信息,这块处理请求前的操作
return config // 拦截之后必须得return出去,不然后台接收不到请求
}, err => {
console.log(err);
})
// 2.2 响应拦截器
instance.interceptors.response.use(res => {
// 这块处理响应前的操作
return res.data
},err => {
console.log(err);
})
// 3.返回promise对象,在组件中执行then、catch等
return instance(config)
}
组件中调用:
import {
request } from '../network/request.js';
export default {
name: '',
data() {
return {
};
},
created() {
// 封装request模块
request({
url: '/home/data'
}).then(res => {
// 成功时执行
console.log(res);
}).catch(err => {
// 异常时执行
console.log(err);
});
}
};
简单示例:
function ysz(){
return new Promise((resolve, reject)=>{
let sino = parseInt(Math.random() * 6 +1)
setTimeout(()=>{
resolve(sino)
},3000)
})
}
async function test(){
let n =await ysz()
console.log(n)
}
test()
await返回Promise对象:
async function queryData(){
const ret = await axios.get('/data')
return ret.data
}
queryData().then(ret=>{
console.log(ret)
})
await返回异步结果:
async function queryData(){
var ret = await new Promise(function(resolve,reject){
setTimeout(function(){
resolve('nihao')
},1000)
})
return ret
}
queryData().then(data=>{
console.log(data) // nihao
})
多个异步请求的场景
axios.defaults.baseURL = 'http://localhost:3000'
async function queryData(){
var info = await axios.get('data1')
var ret = await axios.get('data2?info=' + info.data)
return ret.data
}
queryData().then(data=>{
console.log(data) // world
})
// server接收,并发送给client
app.get('/data1',(req,res)=>{
res.send('hello');
})
app.get('/data2',(req,res)=>{
if(req.query.info == 'hello'){
res.send('world')
}else{
res.send('error')
}
})