同步:一件事没做完,只能等待完成之后才能去做另一件,代码按照顺序依次执行。
异步:无论这件事情是否做完,可以在执行结束之后坐另一间事情,两件事情可以同时进行。
获取异步数据,需要利用回调函数获取数据,想要控制获取数据的顺序,需要嵌套回调函数,当获取的数据量大的时候,会引发回调地狱的问题。此时需要解决回调地狱。
执行顺序:同步程序执行结束后,执行异步程序。
单线程:js是单线程的,只能等待一个任务结束之后才能执行另一个任务。
常见的两种异步情况:
- ajax请求
- 计时器:setTimeout、setInterval
异步问题:
演示异步:
使用计时器函数等待2s,计时器结束后函数return '哈哈'
在计时器函数下面输出函数返回值,我们预期的结果是等待2s之后再输出哈哈,但是程序异步执行,并发执行,先执行下面的输出“返回语句”,然后等待2s之后才会执行计时器中定义的语句
: return '哈哈'
,想让异步程序执行顺序按照我们的规定的顺序执行时,需要处理异步问题。
常见的处理异步问题方式:
- 使用回调函数(不推荐使用)
- 使用ES2015提供的Promise对象 ```javascript function getTea(fn) { setTimeout(() => { fn(‘奶茶’); }, 2000); }
function hotPort(fn) { setTimeout(() => { fn(‘火锅’); }, 1000); }
// 回调地狱 getTea((data) => { console.log(data); hotPort((data) => { console.log(data); }); });
// 用回调函数解决异步问题不是一个好的方法,应该使用Promise对象
利用Promise处理异步问题:利用promise中的then可以获取异步数据。
```javascript
let tea = new Promise((resolve, reject) => { // promise是构造函数,new获取
setTimeout(() => {
// 将异步数据传递出来
let result = true;
if (result) {
resolve('奶茶');
} else {
reject('奶茶获取失败');
}
}, 2000);
});
let hotPort = new Promise((resolve, reject) => {
setTimeout(() => {
// 将异步数据传递出来
let result = true;
if (result) {
resolve('火锅');
} else {
reject('火锅获取失败');
}
}, 1000);
});
tea.then(data => {
console.log(data);
return hotPort;
}).then(data => {
console.log(data);
}).catch(error => {
console.log(error);
});
使用async、await解决异步问题:
await后面加上Promise对象,让异步程序更像同步程序一样执行。
let tea = new Promise((resolve, reject) => {
setTimeout(() => {
// 将异步数据传递出来
let result = true;
if (result) {
resolve('奶茶');
} else {
reject('奶茶获取失败');
}
}, 2000);
});
let hotPort = new Promise((resolve, reject) => {
setTimeout(() => {
// 将异步数据传递出来
let result = true;
if (result) {
resolve('火锅');
} else {
reject('火锅获取失败');
}
}, 1000);
});
async function fun() {
let TEA = await tea;
console.log(TEA);
let HOT_PORT = await hotPort;
console.log(HOT_PORT);
}
fun();
总结:
- 解决异步程序:
- 回调函数解决异步编程(不推荐使用)
- Promise构造函数:
- resolve、reject函数,然后在then、catch方法的参数中接受到异步数据。
- async、await:
- 简化了promise
- async修饰函数、await放在Promise对象前面,能接受到Promise对象传入的数据。