深入理解 Promise、async、回调函数和 AJAX

这篇具有很好参考价值的文章主要介绍了深入理解 Promise、async、回调函数和 AJAX。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

简介:本篇博客将介绍 Promise、async、回调函数和 AJAX,这些是在 JavaScript 中处理异步编程和数据交换的关键技术。我们将通过代码示例和解释来详细说明它们的基本用法和优势。

关于promise

下面是一个简单的示例,展示 Promise 的基本用法:

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    const randomNumber = Math.random();
    if (randomNumber > 0.5) {
      resolve(randomNumber);
    } else {
      reject("Error: Number is too small");
    }
  }, 1000);
});

myPromise
  .then((result) => {
    console.log("Success:", result);
  })
  .catch((error) => {
    console.log("Error:", error);
  });

在创建 Promise 对象时,传递的参数是一个执行器函数,它接受两个参数:resolve 和 reject。在执行器函数中执行异步操作,当操作成功完成时调用 resolve() 并传递结果,当操作失败时调用 reject() 并传递错误信息。

使用 then() 方法可以处理 Promise 对象成功的情况,接受一个回调函数作为参数,回调函数的参数就是异步操作的结果。使用 catch() 方法可以处理 Promise 对象失败的情况,接受一个回调函数作为参数,回调函数的参数是错误信息。

可以链式调用多个 then() 方法来处理多个异步操作的结果,每个 then() 方法返回一个新的 Promise 对象,可以继续进行后续的处理或链式调用。

实例演示

场景描述:

这是一个微信小程序的登录页面在该页面中我们要获取用户信息.

getUserInfo() {
  return new Promise((resolve, reject) => {
    wx.getUserProfile({
      desc: '用于完善会员资料',
      success: res => {
        wx.setStorageSync('userinfo', res.userInfo);
        resolve(res.userInfo);
      },
      fail: err => {
        reject(err);
      }
    });
  });
},

login() {
  return new Promise((resolve, reject) => {
    wx.login({
      success: res => {
        var code = res.code;
        wx.request({
          url: '**************',
          method: "GET",
          data: {
            code: res.code,
          },
          success: res => {
            var openid = res.data.data;
            console.log('openid为' + openid);
            wx.setStorageSync('openid', openid);
            this.setData({
              openid: wx.getStorageSync('openid'),
            });

            wx.request({
              url: app.globalData.apiUrl + '/user/login',
              method: "GET",
              data: {
                openId: wx.getStorageSync('openid'),
                avatar: this.data.headImg,
                nickName: this.data.userName,
              },
              header: {
                'content-type': 'json'
              },
              success: res => {
                resolve();
              },
              fail: err => {
                reject(err);
              }
            });
          },
          fail: err => {
            reject(err);
          }
        });
      },
      fail: err => {
        reject(err);
      }
    });
  });
},

getUserProfile(e) {
  this.getUserInfo()
    .then(userInfo => {
      this.setData({
        userName: userInfo.nickName,
        headImg: userInfo.avatarUrl,
        home: userInfo.city
      });
      return this.login();
    })
    .then(() => {
      console.log("登录信息已传给后台!");
      this.onLoad();
    })
    .catch(error => {
      console.error(error);
    });
},

上述代码是一个小程序中的异步函数使用示例,其中包含了使用 Promise 处理异步操作的代码。

getUserInfo() 函数返回一个 Promise 对象,用于获取用户信息。在异步操作成功时,调用 resolve() 并传递用户信息,将用户信息存储在本地缓存中,并将用户信息作为解析后的值进行返回。在异步操作失败时,调用 reject() 并传递错误信息。

login() 函数返回一个 Promise 对象,用于处理用户登录操作。在登录成功后,通过 wx.request() 发起请求,获取用户的 openid 并进行存储。然后,再次通过 wx.request() 发起请求,将用户信息传递给后台进行登录操作。在登录成功时,调用 resolve() 表示登录成功。在登录失败时,调用 reject() 并传递错误信息。

getUserProfile() 是一个触发获取用户信息和登录操作的函数。它首先调用 getUserInfo() 函数获取用户信息,然后通过 then() 方法将用户信息传递给下一个操作,即调用 login() 函数进行登录操作。在登录成功后,输出登录信息并执行 onLoad() 函数。如果在获取用户信息或登录操作过程中发生错误,将捕获并输出错误信息。

通过使用 Promise 可以更好地处理异步操作,避免回调地狱的问题,使代码逻辑更加清晰和可读。在 getUserProfile() 函数中,通过链式调用多个 then() 方法,将多个异步操作串联起来,使代码的执行顺序更加直观。同时,在最后使用 catch() 方法捕获任何错误,以便进行适当的错误处理。

关于async

async 是 JavaScript 中用于定义异步函数的关键字。通过在函数前面加上 async 关键字,可以将一个普通函数转换为异步函数。

异步函数内部可以包含 await 表达式,它可以暂停函数的执行,等待一个 Promise 对象的解析结果,并返回解析后的值。使用 await 可以简化对 Promise 对象的处理,使代码看起来更像是同步执行的。

以下是异步函数的基本用法:

async function myAsyncFunction() {
  // 异步操作,可以包含 await 表达式

  // 等待一个 Promise 对象的解析结果,并返回解析后的值
  const result = await myPromise;

  // 继续执行其他操作
  // ...

  return result;
}

在异步函数内部,可以执行任何需要异步处理的操作,例如网络请求、文件读取等。使用 await 关键字可以等待一个 Promise 对象的解析结果,并将结果赋值给一个变量。

在执行 await 表达式时,函数会被暂停,直到 Promise 对象被解析(即状态变为 resolved)并返回结果。然后,将解析后的结果赋值给变量,并继续执行函数内的其他操作。

异步函数可以通过 return 语句返回一个 Promise 对象,该 Promise 对象的结果将是异步函数的最终返回值。

以下是一个简单的示例,展示异步函数的基本用法:

async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    return data;
  } catch (error) {
    console.log('Error:', error);
    throw error;
  }
}

fetchData()
  .then((data) => {
    console.log('Data:', data);
  })
  .catch((error) => {
    console.log('Error:', error);
  });

在这个示例中,fetchData() 是一个异步函数,它使用 await 等待 fetch() 方法返回的 Promise 对象解析,并使用 await 等待响应的 JSON 数据解析。如果发生错误,它会将错误抛出并被 catch 语句捕获。

在使用异步函数时,记得在调用函数的地方使用 .then().catch() 方法处理异步函数的结果或错误。

关于回调地狱

回调地狱(Callback Hell)是指在异步编程中,多个回调函数嵌套使用形成的复杂和难以维护的代码结构。当一个异步操作完成后需要执行下一个异步操作,并且这些操作之间存在依赖关系时,往往需要使用回调函数进行处理。如果这种嵌套回调的使用过多,代码就会变得混乱、难以理解和维护,形成了回调地狱。

回调地狱的主要问题是代码缩进层级深,导致代码可读性差、可维护性差。由于每个异步操作的回调函数需要嵌套在前一个回调函数内部,代码的结构会变得非常复杂。当异步操作嵌套多层时,代码的垂直缩进会增加,导致代码难以阅读和理解。同时,如果需要修改其中某个异步操作或添加新的异步操作,就需要修改多个回调函数,增加了代码的脆弱性和出错的可能性。
下面是一个node.js的回调地狱演示

//异步回调地狱(通过callback获取返回值案例一)
const fs = require('fs')
const path = require('path')
let path1 = path.join(__dirname, 'test.txt')
let path2 = path.join(__dirname, 'test2.txt')
let path3 = path.join(__dirname, 'test3.txt')
fs.readFile(path1, 'utf-8', function(error, data) {
  if (error) console.log('error1');
  console.log(data);
  fs.readFile(path2, 'utf-8', function(error, data) {
    if (error) console.log('error2');
    console.log(data);
    fs.readFile(path3, 'utf-8', function(error, data) {
      if (error) console.log('error3');
      console.log(data);
    })
  })
})

在这个回调地狱的案例中,可以使用async/await来改善代码的可读性和可维护性。下面是使用async/await重写该代码的示例:

const fs = require('fs');
const path = require('path');

function readFileAsync(path) {
  return new Promise((resolve, reject) => {
    fs.readFile(path, 'utf-8', (error, data) => {
      if (error) {
        reject(error);
      } else {
        resolve(data);
      }
    });
  });
}

async function readFileData() {
  try {
    const path1 = path.join(__dirname, 'test.txt');
    const path2 = path.join(__dirname, 'test2.txt');
    const path3 = path.join(__dirname, 'test3.txt');

    const data1 = await readFileAsync(path1);
    console.log(data1);

    const data2 = await readFileAsync(path2);
    console.log(data2);

    const data3 = await readFileAsync(path3);
    console.log(data3);
  } catch (error) {
    console.log('error:', error);
  }
}

readFileData();

在上述代码中,我们创建了一个readFileAsync函数,该函数返回一个Promise对象,用于异步读取文件内容。然后,在readFileData函数中使用await关键字来等待每个异步读取操作完成,并通过try/catch块来捕获可能的错误。

使用async/await的方式可以使代码看起来更加简洁和同步化,避免了嵌套的回调函数。每个异步操作都可以像同步代码一样顺序执行,提高了代码的可读性和可维护性。

回调函数(Callback)

回调函数是一种常见的编程概念,指的是将一个函数作为参数传递给另一个函数,在适当的时候被调用执行。

在 JavaScript 中,函数是一等公民,因此可以将函数作为参数传递给其他函数。这种将函数作为参数传递并在需要的时候调用的方式,就是回调函数的基本概念。

回调函数常用于处理异步操作、事件处理、定时器等场景,以确保在某个特定事件发生或操作完成后执行相应的操作。

以下是一个使用回调函数的示例,展示了如何处理异步操作:

function fetchData(callback) {
  setTimeout(function() {
    var data = 'This is the fetched data.';
    callback(data);
  }, 2000);
}

function processData(data) {
  console.log('Processing data:', data);
}

fetchData(processData);

在上面的例子中,我们定义了两个函数:fetchDataprocessDatafetchData 函数模拟一个异步操作,使用 setTimeout 延迟 2000 毫秒后,调用传递的回调函数,并将获取的数据作为参数传递给回调函数。

processData 函数是作为回调函数传递给 fetchData 的,它接收数据作为参数,并在控制台中打印出来。

通过调用 fetchData(processData) ,我们将 processData 函数作为回调函数传递给 fetchData。当数据获取完成后,fetchData 调用传递的回调函数,将获取的数据传递给 processData 函数,并在控制台中输出。

这个示例展示了回调函数的基本用法,通过回调函数我们可以处理异步操作的结果,并执行相应的逻辑。回调函数可以根据需要自定义,并且可以在不同的场景中灵活应用,使我们能够编写更加灵活和可扩展的代码。

事件循环(Event Loop)机制

JavaScript的事件循环(Event Loop)是一种用于处理异步操作的机制。它负责管理代码的执行顺序,确保异步任务能够按照正确的顺序被执行。

在JavaScript中,事件循环维护一个任务队列(Task Queue)和一个调用栈(Call Stack)。所有的同步任务都会按照它们在代码中的顺序被添加到调用栈中执行,而异步任务则会被放置在任务队列中等待执行。

当调用栈为空时,事件循环会检查任务队列。如果任务队列中有任务,事件循环会将队列中的第一个任务推入调用栈中执行。这样,异步任务就能够在适当的时机被执行。

总结来说,事件循环机制通过不断地将任务队列中的任务推入调用栈中执行,实现了JavaScript的异步编程能力。这种机制使得JavaScript能够处理诸如定时器、事件监听和网络请求等异步操作。

AJAX

"AJAX(Asynchronous JavaScript and XML)是一种用于在后台与服务器进行异步数据交换的技术。它允许在不刷新整个页面的情况下发送异步 HTTP 请求,并处理服务器返回的数据。

在现代 Web 应用中,AJAX 的应用非常广泛。它可以用于增强用户体验、提高网页的交互性和效率,并降低服务器的负载。通过 AJAX,我们可以在后台与服务器进行数据交换,而不会打断用户的当前操作。

使用 JavaScript 进行 AJAX 请求的基本步骤如下:

  1. 首先,创建一个 XMLHttpRequest 对象或使用现代的 Fetch API,它们提供了发送 HTTP 请求和处理响应的功能。 例如,可以通过以下方式创建 XMLHttpRequest 对象: var xhr = new XMLHttpRequest();
  2. 然后,配置请求参数,包括请求的方法(GET、POST 等)、URL 和是否异步等。 使用 XMLHttpRequest,可以通过以下代码设置请求: xhr.open(‘GET’, ‘http://*******’, true);
  3. 接下来,监听响应事件。为 XMLHttpRequest 对象添加一个事件监听器,以便在接收到响应时执行相应的操作。 例如,可以使用以下方式监听响应: xhr.onload = function() { if (xhr.status === 200) { // 处理成功响应 var responseData = JSON.parse(xhr.responseText); } else { // 处理错误响应 } };
  4. 最后,发送请求。通过调用 XMLHttpRequest 对象的 send() 方法或使用 Fetch API 来发送请求。 例如,可以通过以下代码发送请求: xhr.send();

在 AJAX 请求中,我们需要注意错误处理。请求可能会遇到网络错误、服务器错误或响应处理错误。我们可以检查响应的状态码,处理成功响应和错误响应,并进行相应的错误处理。

此外,AJAX 请求可能会面临跨域问题。由于浏览器的同源策略,我们不能直接进行跨域请求。为了解决这个问题,可以使用 CORS(跨域资源共享)或 JSONP(JSON with Padding)等技术。

在实际应用中,有一些 AJAX 的最佳实践值得我们遵循。例如,合理设置请求头、选择合适的请求方法、避免过多的并发请求、使用适当的数据格式(如 JSON)等。

除了原生的 AJAX 实现,许多前端框架(如 Vue.js、React)提供了封装的 AJAX 功能,使得使用 AJAX 变得更加方便。此外,还有一些第三方库(如 Axios、jQuery)也提供了简化 AJAX 请求的方法。

总结来说,AJAX 是一种重要的技术,用于在后台与服务器进行异步数据交换。它在现代 Web 应用中发挥着重要的作用,通过 JavaScript 可以轻松地进行 AJAX 请求,并处理响应数据。"

结论:

Promise、async/await、回调函数和 AJAX 是 JavaScript 中处理异步编程和数据交换的重要技术。它们提供了不同的方法来处理异步任务,并使代码更具可读性和可维护性。通过深入理解它们的用法和原理,我们可以编写更高效和可扩展的代码,并改善用户体验。文章来源地址https://www.toymoban.com/news/detail-496423.html

到了这里,关于深入理解 Promise、async、回调函数和 AJAX的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 彻底理解Promise和async/await

    1.异步行为是 为了优化因计算量大而时间长的操作 . 2.pedding 待定: 表示尚未开始或正在进行中    fulfilled 解决: 表示已经成功完成    rejected 拒绝: 表示没有完成 3.从pedding状态切换到fulfilled状态或rejected状态后,状态就不会再改变.而且也不能保证promise比如会脱离待定状态. 因此

    2024年02月03日
    浏览(48)
  • Promise, Generator, async/await的渐进理解

         作为前端开发者的伙伴们,肯定对Promise,Generator,async/await非常熟悉不过了。Promise绝对是烂记于心,而async/await却让使大伙们感觉到爽(原来异步可以这么简单)。可回头来梳理他们的关联时,你惊讶的发现,他们是如此的密切相关。       我对他们三者之间的关联

    2024年02月08日
    浏览(41)
  • Ajax_4(进阶)同步异步+ 宏任务微任务 + Promise链 + async终极解决方案 +事件循环原理 + 综合案例

    01-同步代码和异步代码 什么是同步代码? 同步代码:逐行执行,需要原地等待结果后,才继续向下执行。 什么是异步代码? 调用后耗时,不阻塞代码继续执行,(不必原地等待),在将来完成后 触发一个 回调函数 。 代码阅读 目标:阅读并回答代码执行和打印的顺序 打印

    2024年02月13日
    浏览(51)
  • 深入学习JavaScript系列(七)——Promise async/await generator

    本篇属于本系列第七篇 第一篇:#深入学习JavaScript系列(一)—— ES6中的JS执行上下文 第二篇:# 深入学习JavaScript系列(二)——作用域和作用域链 第三篇:# 深入学习JavaScript系列(三)——this 第四篇:# 深入学习JavaScript系列(四)——JS闭包 第五篇:# 深入学习JavaScrip

    2023年04月08日
    浏览(48)
  • 深入理解 JavaScript Promise

    JavaScript中的Promise是一种处理异步操作的机制,它提供了一种优雅的方式来处理回调函数地狱和异步代码的流程控制。本文将深入介绍JavaScript中的Promise,帮助读者更好地理解和应用Promise。 Promise是一个代表异步操作的对象,它可以有三种状态:pending(进行中)、fulfilled(已

    2024年02月09日
    浏览(67)
  • 【.NET Core】深入理解async 和 await 理解

    async 和 await 是C#5.0时代引入异步编程的核心。通过使用异步编程,你可以避免性能瓶颈并增强程序响应能力。但是,编写异步应用程序的传统技术可能比较复杂,使异步编程难编写,调试和维护。 C#中的 async 和 await 是异步编程的核心。通过这两个,可以

    2024年02月20日
    浏览(47)
  • bootstrap-modal调用ajax后不经过回调函数

    说明:我用的是boostrap的弹框,表单用的是layui的,个人觉得bootstrap比layui的弹框好看点,能自适应高度。 如图:点击保存后里面的内容不执行 原因:type用的是submit 解决:把submit改为button

    2024年02月12日
    浏览(48)
  • 前端框架前置学习(3) AJAX原理 XMLHttpRequest,Promise,简易axios函数封装

    1.获取图片文件对象  // 文件选择元素-change改变事件 document.querySelector(\\\'.upload\\\').addEventListener(\\\'change\\\', e = {       // 1. 获取图片文件       console.log(e.target.files[0]) 2.使用FormData携带文件  // 2. 使用 FormData 携带图片文件       const fd = new FormData()       fd.append(\\\'img\\\', e.target.files[0

    2024年02月03日
    浏览(64)
  • Jquery使用ajax的success回调函数不执行,但是能正常请求

            好久没有写代码了,今天使用 jq 的时候发现success回调函数怎么都不执行。         而且令人不解的是,后端居然都成功接收请求,一切正常。 看了网上很多回答,大概有这几点: 将dataType的值从json改为txt 将dataType属性删除 将error的回调函数补上 ... 我都试过了,最

    2024年02月10日
    浏览(43)
  • 前端(十二)——深入理解和使用 async和await

    😛博主:小猫娃来啦 😛文章核心: 深入理解和使用 async和await 在 JS中,异步操作是无法避免的,而处理异步操作最常用的方法是使用回调函数或者 Promise 。然而,自 ES2017 引入了 async/await 之后,我们可以通过更简洁、可读性更好的方式来处理异步代码。本文将从浅层次到深

    2024年02月12日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包