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("脚本结束");
- 将这段代码放在body下面
- 将这段代码放在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用法
- 创建promise
let promise = new Promise((resolve, reject) => {// 异步操作if (/* 操作成功 */) {resolve(value); // 成功时调用} else {reject(error); // 失败时调用}
});
- 使用 Promise:
- then():接收两个函数作为参数,第一个函数在 Promise 成功时调用,第二个在失败时调用。
promise.then(value => { /* 成功时的处理 */ },error => { /* 失败时的处理 */ }
);
- catch():用于捕获 Promise 中发生的错误。
promise.catch(error => { /* 错误处理 */ }
);
- finally():无论 Promise 最终状态如何都会执行。
promise.finally(() => {// 总是会执行的代码
});
- 链式调用:可以将多个
.then()
和.catch()
串联起来,形成链式调用。 - 静态方法:
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需要请求另一个接口才能拿到。
任务:
- 创建一个请求id的函数,该函数返回一个promise,该promise在2秒后解决(成功),返回一个数字(也即指定商品列表的id)(提示:2秒后成功解决,请用
setTimeout
来模拟) - 创建一个请求商品列表的函数,该函数接受一个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>