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

简介本篇博客介绍 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://blog.csdn.net/kilig_CSM/article/details/131344987

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_8303.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注