Ajax封装理论笔记---回调函数和promise两种方式

55 阅读3分钟

一、同步和异步思想

在软件世界中,

同步任务:当一个操作开始执行后,主程序等待它执行完成,才能继续向下执行;

异步任务:当一个操作开始执行后,主程序无需等待它执行完成,就可以继续向下执行,此操作与主程序同时(并发)执行。

二、回调函数

1.一个函数中以形参形式调用另一个函数,被调用的函数就称回调函数

2.作用:常用于解决异步编程问题

3.常用两种写法

//方式一
function c1(){
     console.log('我是回调函数');
}
function a(c1) {
       c1()
}
//方式二:匿名函数方式
function a(function (){
    console.log('我是回调函数');
}) 

案例:简要封装[Ajax]

js:
const router=require("./router.js")
router.get("/ajax1",function(req,res){
	res.end('{"name":"karen","age":20}')
})
router.get("/ajax2",function(req,res){
	res.end('{"name":"jack","age":22}')
})


html:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script>
			function myjq(url,cb){
				var xhr=new XMLHttpRequest()
				xhr.open("GET",url,true)
				xhr.send()
				xhr.onreadystatechange=function(){
					if(xhr.readyState==4&&xhr.status==200){
						cb(xhr.responseText)
					}
				}
			}
		</script>
	</head>
	<body>
		<button onclick="fn()">ajax1</button>
		<script>
			function fn(){
				console.log(11112)
				//用ajax的工具函数请求url
				var url="http://192.168.6.60:8080/ajax1"
				myjq(url,function(data){
					console.log(data)
				})
			}
			
		</script>
		
		<button onclick="fn2()">ajax2</button>
		<script>
			function fn2(){
				var url2="http://192.168.6.60:8080/ajax2"
				myjq(url2,(data)=>{
					console.log(data)
				})
			}
			
		</script>
	</body>
</html>

1.promise是ES6提供的一个解决异步编程的对象,包含异步操作的结果(成功、失败)

2.作用:①实现异步编程;

    ②用于替代回调函数,解决回调函数嵌套问题--(回调地狱)。

3.promise对象的特点: ①对象的状态不受外界影响;promise对象只有三种状态:pending(进行中)、fulfilled(已成功)、rejected(已失败)。

    ②promise对象一旦改变状态就不会再变,任何时候都可以得到这个结果;
    状态改变只有两种可能:
    由pending改变为fulfilled、由pending改变为rejected;
只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。

首先得了解promise的用法和实用意义:

对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态: 1.pending: 初始状态,不是成功或失败状态。 2.fulfilled: 意味着操作成功完成。 3.rejected: 意味着操作失败。 只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是 Promise 这个名字的由来,它的英语意思就是「承诺」,表示其他手段无法改变。

一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的接口,使得控制异步操作更加容易

案例:用promise简单实现Ajax的封装

<script>
			function  myaxios (url) {
				var p1=new Promise(function(n1,n2){
					var xhr=new XMLHttpRequest()
					xhr.open("GET",url,true)
					xhr.send()
					xhr.onreadystatechange=function(){
						if(xhr.readyState==4&&xhr.status==200){
							n1(xhr.responseText)
						}else if(xhr.readyState==4&&xhr.status==404){
							n2(xhr.responseText)
						}
					}					
					// n1(200)
				})
				return p1
			}
		</script>


<button onclick="fn()">ajax1</button>
		<script>
			function fn(){
				var url="http://192.168.6.60:8080/ajax1"
				myaxios(url).then((res)=>{
					console.log(res,1111)
				})
				
			}
			
		</script>

案例:

function ajaxPromise(position) {
  // 1. 创建AJAX核心对象
  const xhr = new window.XMLHttpRequest
  //创建一个新的Promise对象
  return new Promise((resolve, reject) =>{
      //resolve存储响应成功数据,reject存储响应失败数据
      //get请求
      if (position.method.toUpperCase() == 'GET') {
          // 2. 建立连接
          xhr.open('GET', position.url + '?' + formateParme(position.data))
          xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
          // 3.发送请求
          xhr.send()
      } else if (position.method.toUpperCase() == 'POST') { //post请求
          // 2. 建立连接
          xhr.open('POST', position.url)
          xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
          // 3.发送请求
          xhr.send(formateParme(position.data))
      }
      //4.处理响应结果
      xhr.onreadystatechange = function () {
          if (xhr.readyState == 4) {
              if (xhr.status == 200) {
                  resolve(xhr.responseText)
              }else{
                  reject('网络出错'+xhr.status) 
              }
          }
      }
  })
}
function formateParme(data) {
  let arr = []
  for (const key in data) {
    let item = `${key}=${data[key]}` // username=admin ,password=123
    arr.push(item) //[username=admin,password=123]
  }
  return arr.join('&')
}

调用

ajaxPromise({
      //参数
      method: 'post',
      url: 'http://10.7.171.124:8088/api/login',
      data: {
        username: usernameInput.value,
        password: passwordInput.value
      }
    }).then(success=>{
        //处理响应结果
      let data =JSON.parse(success)
        if (data.resultCode == -1) {
          alert('用户名或密码出错')
        } else {
        alert('登录成功')
          // 跳转到主界面
          location.href = 'index.html'
        }
    })