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>