异步操作、Promise和axios

发布于:2024-12-18 ⋅ 阅读:(50) ⋅ 点赞:(0)

1.Javascript是单线程的

什么是进程,什么是线程?

进程:进程是操作系统分配资源和调度的基本单位。它是一个程序的实例,包含了运行程序所需的代码和数据以及其它资源。

线程:线程是进程中的实际运行单位,也是操作系统分配CPU时间的基本单位。一个进程可以包含一个或多个线程

以浏览器举例,一个浏览器的tab,他就是一个独立的进程,而在这个进程里面跑着各种各样的线程,比如专门负责渲染网页的线程,专门用来跑javascript的线程,

而在这其中 javascript的线程,是单线程,单线程的意思是:也即在同一时间,只会有一个js任务在执行。

如果同一时间,有多个js进程在执行,那么如果他们同时操作了dom,以谁为准???当然还会带来更多的问题,所以,javascript只能是单线程的

// 模拟一个耗时操作
      function longRunningTask() {
        console.log("开始执行耗时任务...");
        const start = Date.now();
        while (Date.now() - start < 1000) {
          // 模拟耗时5秒的同步操作
        }
        console.log("耗时任务结束");
      }

      // 主代码
      console.log("脚本开始");

      longRunningTask(); // 调用同步任务,阻塞线程

      console.log("脚本结束");
  1. 将这段代码放在body下面
  2. 将这段代码放在head中

2.异步操作(异步编程)、同步操作

异步操作是指在编程中,某个任务的执行不会立即完成同时不会阻塞后续代码的执行。在异步操作中,程序可以继续运行,并在异步任务完成时得到通知并处理结果。这与同步操作相对,同步操作会阻塞程序的继续执行直到任务完成。

2.1 异步解决的问题

如果没有异步,那么你每请求一个接口,页面都将不能被滑动,呈现出来就是一卡一卡的

3.回调函数

回调函数是最基本的异步处理方式。在异步操作完成后,调用预先传入的函数

// 示例:使用回调函数进行异步操作
function fetchData(callback) {
    setTimeout(() => {
        const data = "Hello, World!";
        callback(data);
    }, 1000);
}

fetchData((data) => {
    console.log(data);  // 1秒后输出 "Hello, World!"
});

问题:会带来回调地狱

解决的问题:回调地狱

没有promise的时候,都会采用回调函数的方案来进行异步操作

也就是多个回调放一起嵌套起来

// getUserInfo -> getConnectList -> getOneManConnect()
getUserInfo(
  (res) => {
    getConnectList(
      res.user_id,
      (list) => {
        getOneManConnect(
          list.one_man_id,
          (message) => {
            console.log('这是我和某位用户的聊天记录');
          },
          (msg_err) => {
            console.log('获取详情失败');
          }
        );
      },
      (list_err) => {
        console.log('获取列表失败');
      }
    );
  },
  (user_err) => {
    console.log('获取用户个人信息失败');
  }
);
// 用promise来写:
getUserInfo()
 .then(res => getConnectList(res.user_id))
 .then(list => getOneManConnect(list))
 .then(message => console.log(message))
 .catch(error => console.log(error));

4.Promise

Promise 是 JavaScript es6 的一个特性,它允许你在异步操作(如网络请求)完成后执行某些代码。它代表了一个将来才会知道结果的操作。Promise 可以处于以下三种状态之一:

  • Pending(进行中):初始状态,既没有成功,也没有失败。
  • Fulfilled(已成功):操作成功完成。
  • Rejected(已失败):操作失败。

1.1用法

  1. 创建promise
let promise = new Promise((resolve, reject) => {
  // 异步操作
  if (/* 操作成功 */) {
    resolve(value); // 成功时调用
  } else {
    reject(error); // 失败时调用
  }
});
  1. 使用 Promise
  • then():接收两个函数作为参数,第一个函数在 Promise 成功时调用,第二个在失败时调用。
promise.then(
  value => { /* 成功时的处理 */ },
  error => { /* 失败时的处理 */ }
);
  • catch():用于捕获 Promise 中发生的错误。
promise.catch(
  error => { /* 错误处理 */ }
);
  • finally():无论 Promise 最终状态如何都会执行。
promise.finally(() => {
  // 总是会执行的代码
});
  1. 链式调用:可以将多个 .then().catch() 串联起来,形成链式调用。
  2. 静态方法
  • Promise.all():等待所有的 Promise 完成。
  • Promise.race():返回最先改变状态的 Promise 的结果。
  • Promise.resolve()Promise.reject():快速创建已解决或已拒绝的 Promise。

1.2 图示

5.模拟后端请求的方法:

// 定义一个方法,这个方法里返回一个promise对象
// 使用setTimeout模拟异步操作
// 2秒后返回一个字符串Data
const getData = () =>
  new Promise((resolve) => {
    setTimeout(() => {
      resolve("Data");
    }, 2000);
  });

// 当然,也可以返回一个错误
const getError = () =>
  new Promise((resolve, reject) => {
    setTimeout(() => {
      reject("Error");
    }, 2000);
  });
// 当然也可以通过传入的值判断,返回的是成功还是失败
const get = (value) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (value) {
        resolve("Data");
      } else {
        reject("Error");
      }
    }, 2000);
  });
};

小练习

逻辑:现在有一个商品列表,但是请求商品列表需要一个id,来指定请求的是哪个商品列表,这个id需要请求另一个接口才能拿到。

任务:

  1. 创建一个请求id的函数,该函数返回一个promise,该promise在2秒后解决(成功),返回一个数字(也即指定商品列表的id)(提示:2秒后成功解决,请用setTimeout来模拟)
  2. 创建一个请求商品列表的函数,该函数接受一个id,该promise在3秒后解决(成功),返回一个商品列表,商品列表的数据如下
const data = {
    code:0,
    data:[
  { goodsName: '袜子', price: 20 },
  { goodsName: 'T恤', price: 25 },
  { goodsName: '牛仔裤', price: 50 },
  { goodsName: '连衣裙', price: 70 },
  { goodsName: '运动鞋', price: 80 },
  { goodsName: '夹克', price: 120 },
  { goodsName: '帽子', price: 15 },
  { goodsName: '围巾', price: 30 },
  { goodsName: '手套', price: 18 },
  { goodsName: '裙子', price: 60 },
  { goodsName: '卫衣', price: 90 },
],
}

     3.先调用请求id的函数,返回结果后,再通过.then链式调用请求商品列表的函数,最终打印出商品列表

代码示例:

<template>
</template>

<script setup>
import { ref } from 'vue';
const data = ref('[]')
const getid = () => {
  return new Promise((resolve, project) => {
    setTimeout(() => {
      resolve(2)
    }, 3000)
  })
};

const getlist = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve([{
        code: 0,
        data: [
          { goodsName: '袜子', price: 20 },
          { goodsName: 'T恤', price: 25 },
          { goodsName: '牛仔裤', price: 50 },
          { goodsName: '连衣裙', price: 70 },
          { goodsName: '运动鞋', price: 80 },
          { goodsName: '夹克', price: 120 },
          { goodsName: '帽子', price: 15 },
          { goodsName: '围巾', price: 30 },
          { goodsName: '手套', price: 18 },
          { goodsName: '裙子', price: 60 },
          { goodsName: '卫衣', price: 90 },
        ]
      }]);
    }, 3000);
  });
};
//开始使用getid()函数
getid().then((id) => {
  console.log('成功2' + '+', id);
  return getlist();
}).then((res) => {
  const data = res[0]
  console.log('成功3' + JSON.stringify(data));
})
</script>

<style scoped></style>