09.初识前后端交互~async和await(135~150)

281 阅读8分钟

交互简图

image.png

ajax

ajax简易流程

创建对象XHR new XMLHttpRequest

image.png


配置open(请求方式,请求地址,是否异步)

image.png


send

image.png


接受数据,注册事件

image.png

image.png

image.png

小示例

var xhr = new XMLHttpRequest();
xhr.open('GET', '/api/data', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send();

xhr.onload = function() {
  if (xhr.status === 200) {
    var responseData = JSON.parse(xhr.responseText);
    console.log(responseData);
  }
};

image.png


ajax同步异步

同步(Synchronous)AJAX:

同步AJAX是指在发送AJAX请求后,浏览器会等待服务器返回响应之后再继续执行后续的操作。在同步模式下,浏览器会阻塞页面的其他操作,直到接收到完整的响应或者超时。这意味着在同步AJAX请求期间,用户无法与页面进行交互,页面会处于“冻结”状态。

示例:

var xhr = new XMLHttpRequest();
xhr.open('GET', '/api/data', false); // 第三个参数设为false表示同步请求
xhr.send();

console.log(xhr.responseText); // 在接收到响应后才能执行这行代码

异步(Asynchronous)AJAX:

异步AJAX是指在发送AJAX请求后,浏览器不会等待服务器返回响应,而是立即继续执行后续的操作。在异步模式下,浏览器会将AJAX请求交给浏览器的异步处理机制(如事件循环),然后继续执行后续的代码。当服务器返回响应时,浏览器会触发相应的回调函数来处理响应数据。

示例:

var xhr = new XMLHttpRequest();
xhr.open('GET', '/api/data', true); // 第三个参数设为true表示异步请求
xhr.send();

xhr.onload = function() {
  console.log(xhr.responseText); // 在接收到响应后才会执行这个回调函数
};

不要传false


请求方式

get/post/put/delete/patch

image.png

  1. GET:用于从服务器获取资源。GET请求的特点是幂等性,即多次发送相同的GET请求,服务器的响应应该是一致的。GET请求将数据附加在URL的末尾,长度有限制,适用于获取数据。
  2. POST:用于向服务器提交数据。POST请求的特点是非幂等性,即多次发送相同的POST请求,服务器的响应可能会有所不同。POST请求将数据放在请求体中,没有对数据长度的限制,适用于提交数据。
  3. PUT:用于更新服务器上的资源。PUT请求是幂等的,即多次发送相同的PUT请求,服务器的资源应该是一致的。PUT请求将数据放在请求体中,用于更新整个资源。
  4. DELETE:用于删除服务器上的资源。DELETE请求是幂等的,即多次发送相同的DELETE请求,服务器的响应应该是一致的。DELETE请求没有请求体,用于删除资源。
  5. PATCH:用于部分更新服务器上的资源。PATCH请求是非幂等的,即多次发送相同的PATCH请求,服务器的响应可能会有所不同。PATCH请求将数据放在请求体中,用于部分更新资源。
  6. HEAD:获取服务器响应的头信息,但不获取响应体。HEAD请求用于仅获取资源的元数据,如响应头中的Content-Type、Content-Length等。
  7. OPTIONS:获取服务器支持的请求方法和响应头信息。OPTIONS请求用于了解服务器所支持的请求方法,方便客户端进行下一步的请求。
  8. CONNECT:建立与目标资源之间的隧道。CONNECT请求用于与代理服务器建立加密连接,通常用于HTTPS代理。
  9. HEADER:用于在请求中添加自定义的请求头信息。HEADER请求可以通过添加自定义的请求头来传递特定的信息。

例如

var xhr = new XMLHttpRequest();
xhr.open('GET', 'ajax_info.txt', true);
xhr.send();

ajax-封装

在JavaScript中,我们通常会封装Ajax请求,以便更方便地使用它。以下是一个简单的Ajax封装的例子:

function ajax(options) {
    // 创建一个XMLHttpRequest对象
    var xhr = new XMLHttpRequest();

    // 处理返回数据
    xhr.onreadystatechange = function() {
        if(xhr.readyState === 4) {
            if(xhr.status === 200) {
                options.success && options.success(xhr.responseText);
            } else {
                options.error && options.error(xhr.status);
            }
        }
    }

    // 处理请求参数
    var params = '';
    for(var key in options.data) {
        params += key + '=' + options.data[key] + '&';
    }
    params = params.substr(0, params.length - 1);

    // 根据请求类型发送请求
    if(options.type === 'GET') {
        xhr.open('GET', options.url + '?' + params, true);
        xhr.send(null);
    } else if(options.type === 'POST') {
        xhr.open('POST', options.url, true);
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        xhr.send(params);
    }
}

这个封装的函数可以接受一个options对象作为参数,其中可以包含以下属性:

  • type:请求类型,可以是'GET'或'POST'。
  • url:请求的URL。
  • data:发送的数据,应该是一个对象。
  • success:一个在请求成功时调用的函数,该函数接受服务器返回的数据作为参数。
  • error:一个在请求失败时调用的函数,该函数接受HTTP状态码作为参数。

例如,我们可以这样使用这个函数:

ajax({
    type: 'GET',
    url: 'test.php',
    data: {name: 'John', age: 30},
    success: function(response) {
        console.log('Data received: ' + response);
    },
    error: function(status) {
        console.log('Error: ' + status);
    }
});

这样,我们可以更方便地发送Ajax请求,而不需要每次都创建和配置XMLHttpRequest对象。


ajax-前后端交互案例

image.png

image.png

image.png

image.png

image.png


回调地狱问题

在JavaScript中,当我们使用AJAX进行异步操作时,经常会遇到需要多个操作按顺序执行的情冚。例如,我们需要先从服务器获取数据,然后使用这些数据进行下一步操作,然后再进行下一步操作。

如果我们使用传统的回调函数来处理这种情况,代码会变得非常复杂,这就是所谓的“回调地狱”。例如:

ajax('url1', function(response1) {
  ajax('url2', function(response2) {
    ajax('url3', function(response3) {
      // do something with response1, response2 and response3
    });
  });
});

这种代码的问题在于,它们的嵌套使得代码的阅读和理解变得困难,而且如果我们需要处理错误,那么每个回调函数都需要添加错误处理代码,这使得代码更加复杂。

image.png


promise基础语法

在JavaScript中,Promise是一种处理异步操作的对象。它可以代表一个值,该值可能是当前已知的,也可能是在某个时间点在未来才知道。Promise主要有三种状态:pending(待定),fulfilled(已实现),rejected(已拒绝)

Promise的基础语法如下:

let promise = new Promise(function(resolve, reject) {
  // some code
  if (/* everything is fine */) {
    resolve("Worked!");
  } else {
    reject(Error("It broke"));
  }
});

// 使用.then方法处理resolve和reject的结果
promise.then(function(result) {
  console.log(result); // "Worked!"
}, function(err) {
  console.log(err); // Error: "It broke"
});

在这个例子中,Promise构造函数接受一个函数作为参数,这个函数带有两个参数:resolve和reject,分别用于处理成功和失败的情况。

.then方法接受两个参数:一个是promise成功时的回调,另一个是promise失败时的回调。


promise封装ajax

以下是一个使用Promise封装ajax请求的案例,其中包含了详细的注释:

// 定义一个函数,接受url, method, data作为参数
function ajax(url, method, data) {
  // 返回一个新的Promise对象
  return new Promise(function(resolve, reject) {
    // 创建一个新的HTTP请求
    var xhr = new XMLHttpRequest();
    // 初始化一个新的请求
    xhr.open(method, url);
    // 设置请求头,以便服务器知道如何处理传入的请求
    xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");

    // 当请求加载完成时,此函数将被调用
    xhr.onload = function() {
      // 如果请求成功完成,HTTP状态码在200-299之间,则调用resolve函数
      if (xhr.status >= 200 && xhr.status < 300) {
        // 使用请求的响应(response)来resolve promise
        resolve(xhr.response);
      } else {
        // 否则,使用请求的状态文本来reject promise
        reject(Error(xhr.statusText));
      }
    };

    // 当请求发生错误时,此函数将被调用
    xhr.onerror = function() {
      // 使用"网络错误"来reject promise
      reject(Error("网络错误"));
    };

    // 如果有数据需要发送,将其转换为JSON字符串,否则发送null
    var sendData = data ? JSON.stringify(data) : null;
    // 发送请求
    xhr.send(sendData);
  });
}

// 使用示例
// 调用我们定义的ajax函数,进行GET请求
ajax('https://api.example.com/data', 'GET')
  // 如果请求成功,then方法会被调用
  .then(response => {
    console.log('Data loaded successfully');
    // 解析并打印返回的数据
    console.log(JSON.parse(response));
  })
  // 如果请求失败,catch方法会被调用
  .catch(error => {
    console.log('An error occurred');
    // 打印错误信息
    console.log(error);
  });

这个例子中,我们创建了一个ajax函数,它接受一个URL、一个HTTP方法(如'GET'或'POST')和一个可选的数据对象。然后,它创建并返回一个新的Promise对象。如果HTTP请求成功完成,Promise将被resolve(使用HTTP响应作为结果),否则将被reject(使用一个Error对象来表示错误)。


async和await语法

image.png


一、async和 await

  • promise 使用 .then 链式调用,但也是基于回调函数
  • async/await 更加优雅的异步编程的写法
    1.它是消灭异步回调的终极武器
    2.它是同步语法,也就是用同步的写法写异步的代码

案例1:promise异步加载图片

  • 分别使用 .then 和 await 来获取结果
  • 区别
    1.await 完全没有回调函数
    2.await 是同步写法,异步操作
    3.await 后面不仅仅可以接 promise对象,还可以接 async 函数
//里面函数为AJAX,因此是异步任务
let loadImg = (url)=>{
  const p = new Promise((resolve,reject)=>{
    let newImg = document.createElement("img")
	newImg.src = url
	newImg.onload = function(){
	  resolve(newImg)
	}
	newImg.error = function(){
	  reject(new Error('Could not load Image at url'))
	}
  })
  return p
}

//通过 .then 来获取结果
loadImg(url1)
    .then((img)=>{
	  console.log(img.width,img.height)
	  document.body.appendChild(img)
	  return loadImg(url2)
	})
	.then((img)=>{
	  console.log(img.width,img.height)
	  document.body.appendChild(img)
	})
	.catch((err)=>{
	  console.log(err)
	})
	
//使用 async 和 await 的方法来写,立即执行函数
(async function(){
	// loadImg(url1) 返回 promise 对象
	// await 可以拿到从 resolve 传递过来的 dom 对象
	const img1 = await loadImg(url1)  
	document.body.appendChild(img1)
	
	const img2 = await loadImg(url2)  
	document.body.appendChild(img2)
})()

//await 接 async 函数
async function loadImg1(){
  const img1 = await loadImg(url1)
  return img1
}
(async function(){
	//img1可以拿到 resolve 里面的值
	const img1 = await img1 
	document.body.appendChild(img1)
})()

async 和 await(详解)_async和await详解_一生注定学霸命的博客-CSDN博客


总结

累累累累累累

6c22e31b55f450d4eaaa1654b2952e9.jpg