promise异步编排

目录

promise异步编排解决了什么问题:

案例演示

早期Ajax请求代码:

使用更现代的fetch API代替使用XMLHttpRequest对象

GET请求

POST请求

注意事项

 使用promise异步编排

3. 处理 Promise

使用案例(必看,不然理解会不到位):

4. 链式调用

回到案例:

参数

Promise 构造函数

jQuery 的 AJAX 请求

成功和失败的处理



在学习图灵学院前端代码时,看到了promise异步编排解决异步请求问题,所以总结以下文章来串通个人知识点;

promise异步编排解决了什么问题:

Promise 异步编排解决了一系列与 JavaScript 中异步操作相关的问题,这些问题在早期 JavaScript 中使用回调函数时尤为突出。以下是 Promise 异步编排解决的一些主要问题:

  1. 回调地狱(Callback Hell)

    • 在早期的 JavaScript 中,异步操作通常通过嵌套的回调函数来处理,这导致了所谓的“回调地狱”,代码难以阅读和维护。Promise 通过链式调用 .then() 方法提供了一种更扁平化和易于管理的方式来处理异步操作
  2. 错误处理

    • 回调函数中的错误处理通常比较复杂,而且容易遗漏。Promise 提供了 .catch() 方法,允许你集中处理所有异步操作中的错误,而不是在每个回调中单独处理。
  3. 代码的可读性和可维护性

    • Promise 使得异步代码的写法更接近同步代码,提高了代码的可读性和可维护性。
  4. 异步操作的顺序执行

    • 使用 Promise,你可以轻松地按顺序执行异步操作,每个操作的输出可以作为下一个操作的输入。
  5. 状态管理

    • Promise 对象代表了一个异步操作的最终完成(或失败)及其结果值。这使得跟踪和管理异步操作的状态变得更加简单。
  6. 资源清理和最终处理

    • Promise 提供了 finally() 方法,允许你在异步操作完成后执行清理工作,无论操作是成功还是失败。

案例演示

这是早期的Ajax发送异步请求代码(代码来自图灵学院前端代码):

这是通过promise异步编排优化后代码:(两者效果一模一样,但是第二种显然比第一种更加友好)

异步编排解释我放到后面,我先回忆一下早期Ajax代码; 

早期Ajax请求代码:


//new XMLHttpRequest对象
var xhr = new XMLHttpRequest();
//调用回调函数
xhr.onreadystatechange = function(){
    if (this.readyState == 4) {
            if (this.status == 200) {
                 var jsonobj = JSON.parse(this.responseText);
                 jsonstr.success(jsonobj)
             } else {
                  alert(this.status)
             }
     }
}
//打开通道并传入必要参数(请求方式、url、是否支持异步)
xhr.open("method"," url",async)
//发送数据
xhr.send();

 readyState和status解释:

        在Ajax中,正确的术语是readyState和status。readyState指XMLHttpRequest对象的当前状态,其值从0到4变化,表示请求的不同阶段(初始化、载入数据、处理数据、完成请求)。而status则是HTTP响应的状态码,表示服务器返回的状态信息,例如200表示成功,404表示未找到请求的资源。

 使用Ajax发送get请求案例:

//1.创建XMLHttpRequest对象
var xhr = new XMLHttpRequest();
//使用xhr对象调用回调函数
xhr.onreadystatechange=function (){
if (this.readyState == 4) {
        if (this.status == 200) {
            document.getElementById("div1").innerText=this.responseText
        }else{
            alert(this.status)
        }    
    }
}
let value = document.getElementById("ipt1").value;
//打开通道
xhr.open("get","/ajax/ajaxrequest1?value="+value,true)
//发送数据
xhr.send()

使用Ajax发送post请求案例:

//1.创建XMLHttpRequest对象
var xhr = new XMLHttpRequest();
//使用xhr调用回调函数
xhr.onreadystatechange=function (){
    if (this.readyState == 4) {
        if (this.status == 200) {
            document.getElementById("div2").innerText=this.responseText
        }else{
            alert(this.status)
        }
    }
}
//打开通道
xhr.open("post","/ajax/ajaxrequest1",true)
//为post请求添加响应头信息
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded")
let value1 = document.getElementById("ipt1").value;
//发送数据
xhr.send("username="+value1)

为什么在Ajax中需要为post请求设置响应头,而get请求不需要
        在Ajax中,POST请求和GET请求都需要设置响应头。无论请求方式是POST还是GET,服务器端都需要在响应头中设置Content-Type和其他相关的头信息来告知客户端返回的数据类型和编码方式。然而,由于POST请求通常会传递更多的数据,因此在处理POST请求时更加需要注意请求头和响应头的设置。

使用更现代的fetch API代替使用XMLHttpRequest对象

在JavaScript中,发送Ajax请求通常使用XMLHttpRequest对象或者更现代的fetch API。fetch API是基于Promise设计的,它提供了一个更简洁和强大的方式来进行网络请求。以下是使用fetch API发送Ajax请求的基本示例,它符合ES6标准:

GET请求

fetch('https://api.example.com/data')
  .then(response => {
    if (!response.ok) {
      throw new Error('Network response was not ok ' + response.statusText);
    }
    return response.json(); // 或者 response.text() 如果返回的是文本
  })
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    console.error('There has been a problem with your fetch operation:', error);
  });

POST请求

fetch('https://api.example.com/data', {
  method: 'POST', // 或者 'PUT'
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    key1: 'value1',
    key2: 'value2',
  }),
})
.then(response => {
  if (!response.ok) {
    throw new Error('Network response was not ok ' + response.statusText);
  }
  return response.json(); // 或者 response.text() 如果返回的是文本
})
.then(data => {
  console.log(data);
})
.catch(error => {
  console.error('There has been a problem with your fetch operation:', error);
});

  /*

    Response(响应):

        response是指从服务器返回的整个HTTP响应对象。

        它包含了HTTP状态码、响应头、响应体(body)等信息。

        response对象提供了多种方法来处理响应体,例如.json()、.text()、.blob()等,这些方法用于将响应体解析成不同的格式(JSON、文本、二进制数据等)。

        response对象还包含了一些属性,如status(HTTP状态码),ok(布尔值,表示状态码是否在200-299之间),headers(响应头信息)等。

    Data(数据):

        data是指经过处理的响应体内容。

        它是response对象中的响应体经过解析后的结果,例如,如果响应体是JSON格式的,使用response.json()方法解析后,解析出来的JavaScript对象就是data。

        data是应用层真正需要处理的信息,比如API返回的用户信息、商品列表等。

    */

注意事项

  1. 错误处理fetch不会在网络请求失败时抛出错误,只有当HTTP状态码表明请求未成功时(如404或500),才会触发.catch()。网络错误(如断网)会导致fetch promise被拒绝。

  2. Headers:在发送POST请求时,通常需要设置请求头Content-Type

  3. Body:对于POST请求,你需要将数据序列化为JSON字符串。

  4. Async/Await:你还可以使用async/await语法来使异步代码看起来更像同步代码:

async function fetchData(url) {
  try {
    const response = await fetch(url);
    if (!response.ok) {
      throw new Error('Network response was not ok ' + response.statusText);
    }
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('There has been a problem with your fetch operation:', error);
  }
}

// 使用
fetchData('https://api.example.com/data');

使用fetch API可以简化Ajax请求的处理,并且它内置于现代浏览器中,不需要额外的库。

 使用promise异步编排

        Promise 异步编排是指使用 Promise 对象来管理和组织 JavaScript 中的异步操作。Promise 是一种用于异步编程的抽象,它代表了一个异步操作的最终完成(或失败)及其结果值。

Promise 可以通过Promise 构造函数创建:

let myPromise = new Promise((resolve, reject) => {
  // 异步操作
  if (/* 异步操作成功 */) {
    resolve(value); // 将 Promise 状态置为成功,并返回 value
  } else {
    reject(error); // 将 Promise 状态置为失败,并返回 error
  }
});

3. 处理 Promise

  • .then():用于指定当 Promise 成功时的回调函数。
  • .catch():用于指定当 Promise 失败时的回调函数。
  • .finally():无论 Promise 成功还是失败,都会执行的回调函数。
myPromise
  .then(result => {
    // 处理成功的结果
  })
  .catch(error => {
    // 处理错误
  })
  .finally(() => {
    // 无论成功还是失败都会执行
  });

使用案例(必看,不然理解会不到位):

    fetch("https://www.baidu.com")//发送了一个get请求
       .then(response =>{
            if(!response.ok){
                throw new error("网络请求失败");
            }
            return response.json();//使用json()方法解析响应数据,返回Data对象
       })//获取响应数据
       .then(data => console.log(data))//只有上面的then方法成功,才会执行这里的then方法
       .catch(error => console.log(error));//如果get请求失败,处理错误
}

4. 链式调用

Promise 的 .then().catch() 方法返回一个新的 Promise,这允许你进行链式调用。

myPromise
  .then(result1 => {
    // 处理 result1
    return anotherPromise; // 返回另一个 Promise
  })
  .then(result2 => {
    // 处理另一个 Promise 的结果
  });

回到案例:

可以看到这里是创建了一个promise对象,这个对象是用来管理和处理异步请求的内置对象,实际操作中我们并不需要多余的去创建promise对象,来冗余操作,因为在更加现代的fetchAPI 中它隐式的为我们已经创建多promise对象了,我们无需创建,开箱即用即可;

 fetch("https://www.baidu.com")//发送了一个get请求
       .then(response =>{
            if(!response.ok){
                throw new error("网络请求失败");
            }
            return response.json();//使用json()方法解析响应数据,返回Data对象
       })//获取响应数据
       .then(data => console.log(data))//只有上面的then方法成功,才会执行这里的then方法
       .catch(error => console.log(error));//如果get请求失败,处理错误
}

promise对象被隐式的创建在fetch中了;类似下面这样: 

function fetch(url) {
  // 创建一个新的 Promise 对象
  return new Promise((resolve, reject) => {
    // 模拟一个异步操作,比如网络请求
    setTimeout(() => {
      try {
        // 假设我们成功获取到了数据
        const data = { message: 'This is mock data from mockFetch' };
        resolve(data); // 请求成功,调用 resolve
      } catch (error) {
        reject(error); // 请求失败,调用 reject
      }
    }, 1000); // 模拟网络延迟
  });
}

// 使用 fetch
fetch('https://api.example.com/data')
  .then(response => {
    console.log('Response:', response);
  })
  .catch(error => {
    console.error('Error:', error);
  });

在这个示例中:

  1. Fetch 函数接受一个 url 参数,并返回一个新的 Promise 对象。
  2. 在 Promise 构造函数中,我们有两个回调函数:resolve 和 reject
    • resolve 在请求成功时被调用,模拟成功获取数据。
    • reject 在请求失败时被调用,模拟请求失败的情况。
  3. 我们使用 setTimeout 来模拟异步操作,比如网络请求。在延迟后,我们调用 resolve 或 catch 来模拟请求的成功或失败。
  4. 最后,我们使用 .then() 和 .catch() 方法来处理 Promise 的解决和拒绝状态。

这个示例展示了如何手动创建和处理 Promise,帮助你更好地理解 fetch API 背后的工作原理。在实际开发中,fetch API 已经为你处理了这些细节,你只需要关注如何使用它来发送请求和处理响应。

function myAjax(url) {
        return new Promise((resolve, reject) => {
            $ajax({
                url,
                success: function (result) {//浏览器处理完请求后,回调success函数,并将结果作为参数传递result
                    resolve(result);
                },
                error: function (error) {//如果发生错误,回调error函数,并将错误对象作为参数传递error
                    reject(error);
                }
            })
        })
    }

参数

  • url:这是传递给 myAjax 函数的参数,表示要请求的 URL 地址。

Promise 构造函数

  • new Promise((resolve, reject) => { ... }):这里创建了一个新的 Promise 对象。Promise 构造函数接受一个执行器函数,该函数有两个参数:resolve 和 reject
    • resolve:当异步操作成功时调用,将 Promise 的状态从 pending 变为 fulfilled,并返回操作的结果。
    • reject:当异步操作失败时调用,将 Promise 的状态从 pending 变为 rejected,并返回操作的错误。

jQuery 的 AJAX 请求

  • $.ajax:这是 jQuery 提供的 AJAX 请求方法,它接受一个配置对象,包括 urlsuccess 和 error 等属性。
    • url:请求的 URL 地址,这里直接使用 myAjax 函数的参数 url
    • success:当请求成功时调用的回调函数,它接收一个参数 result,表示服务器返回的数据。
    • error:当请求失败时调用的回调函数,它接收一个参数 error,表示错误信息。

成功和失败的处理

  • success: function (result) { resolve(result); }当 AJAX 请求成功时,jQuery 会调用 success 回调函数,并传递服务器返回的数据 result。在这个回调函数中,调用 resolve(result) 将 Promise 的状态设置为 fulfilled,并传递 result 作为结果。这样,任何附加在 myAjax 返回的 Promise 上的 .then() 方法都会被调用,并接收 result 作为参数。
  • error: function (error) { reject(error); }当 AJAX 请求失败时,jQuery 会调用 error 回调函数,并传递错误信息 error。在这个回调函数中,调用 reject(error) 将 Promise 的状态设置为 rejected,并传递 error 作为错误信息。这样,任何附加在 myAjax 返回的 Promise 上的 .catch() 方法都会被调用,并接收 error 作为参数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值