定义:Promise是JS中进行异步编程的新解决方案,代替了单纯使用回调函数。
require('fs').readFile('./index.html',(err,data)=>{})
$.get('/server',(data)=>{})
setTimeout(()=>{},2000)
具体表达:
// Promise 形式实现
// resolve 解决 函数类型的数据
// reject 拒绝 函数类型的数据
const p = new Promise((resolve,reject) => {
setTimeout(() => {
//获取1-100的一个随机数
let n = rand(1,100)
//判断
if(n <= 30){
resolve(n) // 将 promise 对象的状态设置为 【成功】
}else{
reject(n) // 将 promise 对象的状态设置为 【失败】
}
},1000)
})
//调用then 方法
p.then((value) => {
alert('恭喜你中奖了!中奖数字为:',value)
},(reason) => {
alert('再接再厉,您的数字为:',reason)
})
//Promise 形式
let p = new Promise((resolve , reject) => {
fs.readFile('./resource/content.txt',(err, data) => {
//如果出错
if(err) reject(err)
//如果成功
resolve(data)
})
})
//调用 then
p.then(value => {
console.log(value.toString())
}, reason => {
console.log(reason)
})
const p = new Promise((resolve,reject) => {
//1.创建对象
const xhr = new XMLHttpRequest()
//2. 初始化
xhr.open('GET','https://api.apiopen.top/getJok')
//3. 发送
xhr.send()
//4. 处理相应结果
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
//判断相应状态码 2xx
if(xhr.status >= 200 && xhr.status <300){
//控制台输出响应体
resolve(xhr.response)
}else{
//控制台输出相应状态码
reject(xhr.status)
}
}
}
})
p.then(value=>{
console.log(value)
},reason=>{
console.log(reason)
})
//引入 util 模块
const util = require('util')
//引入 fs模块
const fs = require('fs')
//返回一个新的promise函数(可以避免自己手动封装)
let mineReadFile = util.promisify(fs.readFile)
mineReadFile('./resource/content.txt'.then(value => {
console.log(value.toString())
}))
function sendAJAX(url){
return new Promise((resolve,reject) => {
//1.创建对象
const xhr = new XMLHttpRequest()
xhr.responseType = 'json'
//2. 初始化
xhr.open('GET',url)
//3. 发送
xhr.send()
//4. 处理相应结果
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
//判断相应状态码 2xx
if(xhr.status >= 200 && xhr.status <300){
//控制台输出响应体
resolve(xhr.response)
}else{
//控制台输出相应状态码
reject(xhr.status)
}
}
}
})
}
sendAJAX('https://api.apiopen.top/getJok').then(value=>{
console.log(value)
},reason=>{
console.warn(reason)
})
Promise实例对象中的一个属性 【PromiseState】
Promise状态的改变
说明:只有这两种状态改变,并且一个promise对象只能改变一次
无论变为成功还是失败,都会有一个结果数据
成功的结果数据我们一般称为value,失败的结果数据一般称为reason
实例对象中的另一个属性 【PromiseResult】
保存着异步任务【成功/失败】的结果
解释:new Promise后在Promise内部封装自己的异步任务,之后执行异步任务,如果成功了执行resolve(),状态变为resoloved,之后通过then调用成功的回调函数,失败同样
(value) => {}
value:成功的数据或者promise对象
说明:返回一个成功/失败的promise对象
//如果传入的参数为非Promise类型的对象,则返回的结果为成功的promise对象
//如果传入的参数为Promise对象,则参数的结果决定了resolve的结果
let p1 = Promise.resolve(555)
//此时p1状态为resolved,值为555
let p2 = Promise.resolve(new Promise((resolve, reject) =>{
reject('Error!')
}))
//此时P2的状态为rejected,值为Error
p2.catch(reason => {
console.log(reason)
})
无论返回什么值都是失败值,状态都为失败
p3中状态值为失败,失败的结果为传入的那个成功的Promise对象
7.promise.race()
当promise改变为对应的状态时都会调用
promise的then()返回一个新的promise,可以开成then()的链式调用
通过then的链式调用串联多个同步/异步任务
只有一种方式,就是返回一个pedding状态的Promise对象
暂未实现…
async function main(){
//1.如果返回的值是一个非Promise类型的数据
//return 521 //状态为成功 值为返回的这个值
//2.如果返回的是一个Promise对象
return new Promise((resolve,reject) => {
//resolve('ok') 成功
//reject('Error') 失败
//3.抛出异常
throw "oh NO" //失败 值为抛出的这个值
})
}
async function main(){
let p = new Promise((resolve,reject) => {
//resolve('ok') 下面的res返回的是ok
reject('Error')
})
//1.右侧是promise的情况
let res = await p //成功时为成功的值
//2. 右侧为其他类型的数据
let res2 = await 20 //返回20
//3.如果promise是失败的状态
try{
let res3 = await p
}catch(e){
console.log(e) //返回Error
}
}
main()
async和await
//将resource目录下的1.html 2.html 3.html文件内容连接在一起
const fs = require('fs')
const util = require('util')
const mineReadFile =util.promisify(fs.readFile)
// fs.readFile('./resource/1.html',(err,data1) => {
// if (err) throw err
// fs.readFile('./resource/2.html',(err,data2) => {
// if (err) throw err
// fs.readFile('./resource/3.html',(err,data3) => {
// if (err) throw err
// console.log(data1 + data2 + data3)
// })
// })
// })
//async和await
async function main() {
try{
let data1 = await mineReadFile('./resource/1.html')
let data2 = await mineReadFile('./resource/2.html')
let data3 = await mineReadFile('./resource/3.html')
console.log(data1 + data2 + data3)
}catch (e) {
console.log(e.code)
}
}
async和await结合发送Ajax请求
<button id = 'btn'>点击获取段子button>
function sendAJAX(url){
return new Promise((resolve,reject) => {
//1.创建对象
const xhr = new XMLHttpRequest()
xhr.responseType = 'json'
//2. 初始化
xhr.open('GET',url)
//3. 发送
xhr.send()
//4. 处理相应结果
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
//判断相应状态码 2xx
if(xhr.status >= 200 && xhr.status <300){
//控制台输出响应体
resolve(xhr.response)
}else{
//控制台输出相应状态码
reject(xhr.status)
}
}
}
})
}
let btn = document.querySelector('#btn')
btn.addEventListener('click',async function(){
let duanzi = await sendAJAX('http://api.apipoen.top/getJoke')
console.log(duanzi)
})
概念:Axios是专注于网络数据请求的一个库
相比于原生的XMLHttpRequest对象,axios简单易用
相比于jQuery,axios更加轻量化,只专注于网络数据请求
axios发起get请求的语法:
axios.get('url',{params:{/*参数*/}}).then(callback)
//实例代码
var url = 'http://www.liulongbin.top:3006/api/get'
// 请求的参数对象,请求参数 ?name= zs&age=20
var paramsObj = {name:'zs', age:20}
// 调用axios.get() 发起GET请求
axios.get(url, { params:paramsObj }).then(function(res){
//res.data 是服务器返回的数据
var result = res.data
console.log(res)
})
axios发起post请求的语法:
axios.post('url',{/*参数*/}).then(callback)
具体的请求示例如下:
//请求的url地址
var url = 'http://www.liulongbin.top:3006/api/post'
// 要提交到服务器的数据
var dataObj = { location : '北京' , address : '顺义'}
// 调用 axios.post() 发起POST请求
axios.post(url, dataObj).then(function(res){
//res.data 是服务器返回的数据
var result = res.data
console.log(result)
})
axios也提供了类似于jQuery中$.ajax()的函数,语法如下:
axios({
method:'请求类型',
url:'请求的URL地址',
data:{/* POST数据 */},
params:{/* GET参数 */}
}).then(callback)
直接使用axios发起GET请求
axios({
method:'GET',
url : 'http://www.liulongbin.top:3006/api/get',
params:{
//GET参数要通过params属性提供
name:'zs',
age:20
}
}).then(function(res){
console.log(res.data)
})
直接使用axios发起POST请求
axios({
method:'POST',
url:'http://www.liulongbin.top:3006/api/post',
data:{
// POST 数据要通过data属性提供
bookname:'111',
price:666
}
}).then(function(res){
console.log(res.data)
})
//1.获取按钮
const btns = document.querySelectorAll('button')
//第一个
btn[0].onclick = function () {
// 发送AJAX请求
axios({
method:'get',
//url
url:'http://127.0.0.1:3000/posts/2'
}).then(response => {
console.log(response)
})
}
//2.添加一篇新的文章
btn[1].onclick = function () {
// 发送AJAX请求
axios({
method:'post',
//url
url:'http://127.0.0.1:3000/posts',
//设置请求体
data:{
title:'今天天气不错',
author:'张三'
}
}).then(response => {
console.log(response)
})
}
//3.更新数据
btn[2].onclick = function () {
// 发送AJAX请求
axios({
method:'put',
//url
url:'http://127.0.0.1:3000/posts/3',
//设置请求体
data:{
title:'今天天气不错',
author:'左超然'
}
}).then(response => {
console.log(response)
})
}
//4.删除数据
btn[3].onclick = function () {
// 发送AJAX请求
axios({
method:'delete',
//url
url:'http://127.0.0.1:3000/posts/3',
}).then(response => {
console.log(response)
})
}
用axios.request({})方法
const btns = document.querySelectorAll('button')
//发送GET请求
btns[0].onclick = function(){
//axios()
axios.request({
method:'GET',
url:'http://127.0.0.1:3000/comments'
}).then(response => {
console.log(response)
})
}
用axios.post()发送post请求,添加一条comments
const btns = document.querySelectorAll('button')
//发送GET请求
btns[0].onclick = function(){
axios.post(
url:'http://127.0.0.1:3000/comments',
{
"body":'喜大普奔',
"postId": 2
}
).then((response) => {
console.log(response)
})
}
config:请求的配置对象
data:请求体中的内容(数据)
headers:请求头的内容
request:原生的AJAX请求内容
status:请求状态码
statusText:请求内容
const bens = document.querySelectorAll('button')
//默认配置
axios.defaults.method = 'GET' //设置默认的请求类型为GET
axios.defaults.baseURL = 'http://localhost:3000' //设置基础URL
axios.defaults.params = {id:100} //默认参数为id=100 http://127.0.0.1?id=100
axios.defaults.timeout = 3000 //超时时间为3s
btns[0].onclick = function(){
axios({
url:'/posts'
}).then(response => {
console.log(response)
})
}
const btns = document.querySelectorAll('button')
//创建实例对象
const duanzi = axios.create({
baseURl:'https://api.apiopen.top',
timeout: 2000
})
//此时duanzi是axios的一个实例对象,它和axios对象的功能几乎是一样的
//请求方式1
duanzi({
url:'/getJoke'
}).then(response => {
console.log(response.data)
})
//请求方式2
duanzi.get('/getJoke').then(response => {
console.log(response.data)
})
//上述请求方式1和请求方式2效果一样
实例对象有什么作用?
如果我们的项目的接口不是来自于一个服务器,那么使用默认配置就不行了 因为默认配置前面的域名只能设置为一个,可以创建两个axios实例对象,分别用实例对象发起ajax请求
axios拦截器分为请求拦截器和响应拦截器
//Promise
// 设置请求拦截器
axios.interceptors.request.use(function(config){
console.log("请求拦截器 成功")
config.params = {a:100}
return config
//throw 'error' //抛出错误 之后后续的拦截器就只能走失败的拦截器了
},function(error){
console.log('请求拦截器 失败')
return Promise.reject(error)
})
//设置相应拦截器
axios.interceptors.response.use(function(response){
console.log('响应拦截器 成功')
return response.data
},function(error){
console.log('响应拦截器 失败')
return Promise.reject(error)
})
//发送请求
axios({
method:'GET',
url:'http://127.0.0.1:3000/posts'
}).then(response => {
console.log('自定义回调处理成功的结果')
}).catch(reason => {
console.log('自定义失败回调')
})
config参数:配置对象
可以修改config中的参数
response:响应体内容
如果一直都是成功的
如果请求拦截器中抛出了错误
如果有多个请求拦截器和响应拦截器 则请求拦截器后面的先执行 响应拦截器前面的先执行
//获取按钮
const btns = document.querySelectorAll('button')
//2.声明全局变量
let cancel = null
//发送请求
btn[0].onclick = function(){
axios({
method:'GET',
url:'http://localhost:3000/posts',
//1.添加配置对象的属性
cancelToken: new axios.CancelToken(function(c){
//3.将c的值赋值给cancel
cancel = c
}).then(response =>{
console.log(response)
})
})
}
btn[1].onclick = function(){
cancel()
}
检测上一次的请求是否已经完成
//获取按钮
const btns = document.querySelectorAll('button')
//2.声明全局变量
let cancel = null
//发送请求
btn[0].onclick = function(){
//检测上一次的请求是否已经完成
if(cancel !== null){
//如果没有完成 取消上一次的请求
cancel()
}
axios({
method:'GET',
url:'http://localhost:3000/posts',
//1.添加配置对象的属性
cancelToken: new axios.CancelToken(function(c){
//3.将c的值赋值给cancel
cancel = c
}).then(response =>{
console.log(response)
//将cancel的值初始化设置
cancel = null
})
})
}
cancel = c
}).then(response =>{
console.log(response)
})
})
}
btn[1].onclick = function(){
cancel()
}
检测上一次的请求是否已经完成
[外链图片转存中...(img-ijmF3poX-1663677739499)]
```js
//获取按钮
const btns = document.querySelectorAll('button')
//2.声明全局变量
let cancel = null
//发送请求
btn[0].onclick = function(){
//检测上一次的请求是否已经完成
if(cancel !== null){
//如果没有完成 取消上一次的请求
cancel()
}
axios({
method:'GET',
url:'http://localhost:3000/posts',
//1.添加配置对象的属性
cancelToken: new axios.CancelToken(function(c){
//3.将c的值赋值给cancel
cancel = c
}).then(response =>{
console.log(response)
//将cancel的值初始化设置
cancel = null
})
})
}