Ajax + Promise复习简单小结simple

axios使用

先看看老朋友 axios
axios是基于Ajax+promise封装的
看一下他的简单使用
安装:npm install axios --save
引入:import axios from 'axios'

GitHub地址

基本使用

axios({url: 'http://hmajax.itheima.net/api/province'}).then(function (result) {
		const {data: {list, message}, status} = result
		console.log(list, message, status)
})
// 发送 GET 请求(默认的方法)
axios('/user/12345').then(response => {}).catch(error => {})

查询参数

axios({
	url: 'http://hmajax.itheima.net/api/city',
	method: 'get',
	params: {
		pname: '河南省'
	}
}).then(function (result) {
	// const {data: {list, message}, status} = result
	console.log(result)
})

post提交

document.querySelector('button').addEventListener('click', function () {
	axios({
		url: 'http://hmajax.itheima.net/api/register',
		method: 'post',
		data: {
			username: 'itheima123',
			password: '123456'
		}
	}).then(function (result) {
		console.log(result)
	})
})

错误处理

document.querySelector('button').addEventListener('click', function () {
		axios({
			//请求选项
			url: 'http://hmajax.itheima.net/api/register',
			method: 'post',
			data: {
				username: 'itheima123',
				password: '123456'
			}
		}).then(function (result) {
			//处理数据
			console.log(result)
		}).catch(function (error) {
			//处理错误
			console.log(error.response.data.message)
		})
	})

实现一个简单地图片上传在这里插入图片描述

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Title</title>
	<style>
		img {
			height: 200px;
			width: auto;
			border-radius: 20px;
			border: 1px solid rebeccapurple;
		}
	</style>
</head>
<body>
<input type="file" class="upload">
<img/>
</body>
<script type="text/javascript" src="../js/axios.js"></script>
<script type="text/javascript">
	/*
	* 图片上传显示在网页上面
	* 1. 获取图片文件
	* 2. 使用 FormData 携带图片文件
	* 3. 提交到服务器获取到返回的图片服务器地址*/
	document.querySelector('input').addEventListener('change', function (e) {
		console.log(e.target.files[0])
		//FormData对象
		const fd = new FormData()
		fd.append('img', e.target.files[0])
		axios({
			url: 'http://hmajax.itheima.net/api/uploadimg',
			method: 'post',
			data: fd
		}).then(function (result) {
			console.log(result)
			document.querySelector('img').src = result.data.data.url
		}).catch(function (error) {
			console.log(error)
		})
	})
</script>
</html>

XMLhttpRequest使用

/*get请求携带参数*/
/*1. 实例化一个xhr对象*/
const xhr = new XMLHttpRequest()
/*2. 配置请求方法和URL地址*/
xhr.open('get', 'http://hmajax.itheima.net/api/city?pname=辽宁省')
/*3. 添加load事件,获取响应结果*/
xhr.addEventListener('load', function (result) {
	console.log(JSON.parse(result.target.response))
	document.write(JSON.parse(result.target.response).list.join(' , '))
})
/*4. 发起请求*/
xhr.send()
	
/*post请求设置请求头,携带请求体*/
document.querySelector('button').addEventListener('click', () => {
	const xhr = new XMLHttpRequest()
	xhr.open('post', 'http://hmajax.itheima.net/api/register')
	xhr.addEventListener('load', function (result) {
		console.log(JSON.parse(result.target.response))
	})
	/*设置请求头 告诉服务器 内容类型*/
	xhr.setRequestHeader('Content-Type', 'application/json')
	const user = {username: 'itheima093', password:' 123456'}
	const userStr = JSON.stringify(user)
	/*将字符串类型的 请求体发送给服务器*/
	xhr.send(userStr)
})

详细文档参照 MDN

同步异步

  • 同步代码
    • 逐行执行,原地等待结果后,才继续向下执行
  • 异步代码
    • 调用后耗时,不阻塞代码执行,将来完成后触发回调函数

JavaScript中的异步代码有
- setTimeout / setInterval
- 事件
- Ajax

异步代码接收结果!
- 依靠异步的回调函数接收结果

回调地狱

在回调函数中一直向下嵌套回调函数,就会形成回调函数地狱

/*毁掉地狱*/
	new MyAxios({
		url: 'http://hmajax.itheima.net/api/province'
	}).then(result => {
		console.log(result)
		let province = document.querySelector('.province')
		province.innerHTML = result.list.map(item => `<option>${item}</option>`).join('')
		new MyAxios({
			url: 'http://hmajax.itheima.net/api/city',
			params: {pname: province.value}
		}).then(result => {
			console.log(result)
			let city = document.querySelector('.city')
			city.innerHTML = result.list.map(item => `<option>${item}</option>`).join('')
			new MyAxios({
				url: 'http://hmajax.itheima.net/api/area',
				params: {pname: province.value, cname: city.value}
			}).then(result => {
				console.log(result)
				let area = document.querySelector('.area')
				area.innerHTML = result.list.map(item => `<option>${item}</option>`).join('')
			})
		})
	})

缺点:
- 可读性差
- 异常捕获困难
- 耦合性严重

解决:
promise的链式调用
使用then函数返回新的Promise对象的特性一直串联下去

/*链式调用*/
	let province = document.querySelector('.province')
	new MyAxios({url: 'http://hmajax.itheima.net/api/province'}).then(result => {
		console.log(result);
		province.innerHTML = result.list.map(item => `<option>${item}</option>`).join('')
		return new MyAxios({url: 'http://hmajax.itheima.net/api/city', params: {pname: province.value}})
	}).then(result => {
		console.log(result);
		let city = document.querySelector('.city');
		city.innerHTML = result.list.map(item => `<option>${item}</option>`).join('')
		return new MyAxios({url: 'http://hmajax.itheima.net/api/area', params: {pname: province.value, cname: city.value}})
	}).then(result => {
		console.log(result);
		let area = document.querySelector('.area');
		area.innerHTML = result.list.map(item => `<option>${item}</option>`).join('')
	})
使用async 和 await解决(最优)
/*async await 配合使用*/
async function init() {
	let province = document.querySelector('.province')
	let city = document.querySelector('.city');
	let area = document.querySelector('.area');
	console.log('开始执行异步代码')
	/*错误捕获; try 代码块中出现了错误,代码就不会继续往下执行了*/
	try {
		const provinceList = await new MyAxios({url: 'http://hmajax.itheima.net/api/province'})
		province.innerHTML = provinceList.list.map(item => `<option>${item}</option>`).join('')
		const cityList = await new MyAxios({url: 'http://hmajax.itheima.net/api/city', params: {pname: province.value}})
		city.innerHTML = cityList.list.map(item => `<option>${item}</option>`).join('')
		const areaList = await new MyAxios({url: 'http://hmajax.itheima.net/api/area', params: {pname: province.value, cname: city.value}})
		area.innerHTML = areaList.list.map(item => `<option>${item}</option>`).join('')
		console.log(provinceList)
		console.log(cityList)
		console.log(areaList)
	}catch (error) {
		console.dir(error)
	}finally {
		console.log('finally')
	}
}

Promise

Promise 对象表示异步操作最终的完成(或失败)以及其结果值。

三个状态:
pending (初始状态,既没有兑现也没有拒绝) => fulfilled(操作成功) / rejected(操作失败)
Promise对象一旦被兑现或拒绝,就代表该对象就已敲定了,状态将无法在改变

优点:

  • 逻辑更清晰
  • 有助于了解axios的内部运作机制
  • 解决回调函数地狱问题(通过链式调用 then 返回一个新的Promise对象

基本使用

/*使用promise管理异步任务*/
const p = new Promise((resolve, reject) => {
	setTimeout(function () {
		//resolve() => fulfilled状态-已兑现 => then()
		// resolve('成功')
		//reject() => rejected状态-已兑现 => catch()
		reject(new Error('失败'))
	}, 2000)
})

console.log(p)

p.then(result => {
	console.log(result)
}).catch(error => {
	console.log(error)
})

PromiseAll

/*当我们需要执行几个Promise对象,同时获取他们的结果时,使用Promise静态方法Promise.all([])*/
const ps = Promise.all([new Promise(resolve => resolve(1)), new Promise(resolve => resolve(2))])
// 这里的result是一个数组
ps.then(result => console.log(result))
const p1 = new Promise(resolve => resolve(3))
const p2 = new Promise(resolve => resolve(4))
const p3 = new Promise((resolve, reject) => {
	reject('错误1')
})
const p4 = new Promise((resolve, reject) => {
	reject('错误2')
})
// 当执行的过程中发生错误是,会中断执行并抛出第一个错误
Promise.all([p1, p2, p3, p4]).then(result => {
	console.log(result)
}).catch(error => {
	console.log(error)
})

Promise 配合 XMLHttpRequest使用

<script type="text/javascript">
	
	const p = new Promise((resolve, reject) => {
		const xhr = new XMLHttpRequest()
		xhr.open('get', 'http://hmajax.itheima.net/api/city?pname=湖南省')
		xhr.addEventListener('loadend', function (result) {
			if (result.target.status === 200) {
				resolve(JSON.parse(xhr.response))
			} else {
				reject(new Error(xhr.response))
			}
		})
		xhr.send()
	})
	
	console.log(p)
	
	p.then(result => {
		console.log('执行成功', result)
	}).catch(error => {
		//错误对象要是用console.dir详细打印
		console.dir('执行错误', error)
	})
</script>

XMLHttpRequest 配合 Promise进行简单封装和使用

// 封装为一个函数 MyAxios,返回的是一个Promise对象
function MyAxios({method = 'get', url, params, data}) {
    //返回一个Promise对象
    return new Promise((resolve, reject) => {
        /*1. 实例化一个xhr对象*/
        const xhr = new XMLHttpRequest()
        /*判断是否有传参,有传参拼接在URL后面*/
        url = params ? url + function () {
            const keys = Object.keys(params)
            const values = Object.values(params)
            return '?' + keys.map((item, index) => item + '=' + values[index]).join('&')
        }() : url
        // console.log(url)
        xhr.open(method, url)
        // 有请求体,给请求头设置请求体文本类型
        xhr.setRequestHeader('Content-Type', 'application/json')
        /* 添加load事件,获取响应结果 */
        xhr.addEventListener('loadend', function () {
            /*200-300之间的状态码为响应成功状态码*/
            if (xhr.status >= 200 && xhr.status < 300) {
                /*返回的内容类型为JSON字符串,对它进行解析并返回*/
                resolve(JSON.parse(xhr.response))
            } else {
                reject(new Error(xhr.response))
            }
        })
        /*判断是否为post请求*/
        data ? xhr.send(JSON.stringify(data)) : xhr.send()
    })
}

/*get请求 传参*/
/*new MyAxios({
    method: 'get',
    url: 'http://hmajax.itheima.net/api/area',
    params: {
        pname: '河北省',
        cname: '石家庄市'
    }
}).then(result => {
    console.log(result)
}).catch(error => {
    console.log(error)
})*/

/*post请求*/
/*new MyAxios({
    method: 'post',
    url: 'http://hmajax.itheima.net/api/register',
    data: {username: 'itheima095', password:' 123456'}
}).then(result => {
    console.log(result)
}).catch(error => {
    console.log(error)
})*/

/*获取城市天气*/
/*new MyAxios({
    method: 'get',
    url: 'http://hmajax.itheima.net/api/weather',
    params: {
        city: '110100'
    }
}).then(result => {
    console.log(result)
}).catch(error => {
    console.log(error)
})*/

/*获取天气案例*/
document.querySelector('.search-city').addEventListener('input', debounce(fun, 500))
const ul = document.querySelector(`ul`)
function fun(e) {
    console.log('发送请求', e.target.value)
    new MyAxios({
        url: 'http://hmajax.itheima.net/api/weather/city',
        params: {
            city: e.target.value
        }
    }).then(result => {
        console.log(result)
        ul.innerHTML = result.data.map(item => `<li data-code="${item.code}">${item.name}</li>`).join('')
    }).catch(error => {
        console.log(error)
    })
}
ul.addEventListener('click', function (e) {
    const li = e.target
    if (li.tagName === 'LI') {
        console.log(li.dataset.code);
        new MyAxios({
            method: 'get',
            url: 'http://hmajax.itheima.net/api/weather',
            params: {
                city: li.dataset.code
            }
        }).then(result => {
            console.log(result)
        }).catch(error => {
            console.log(error)
        })
    }
})
//防抖函数
function debounce(fun, delay = 500) {
    let timer = null
    return function (e) {
        if (timer)
            clearTimeout(timer)
        timer = setTimeout(function () {
            fun(e)
            timer = null
        }, delay)
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

多喝热水,重启试试

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值