Callback,Promise和Async/Await

JavaScript是单线程语言,但是js中有很多任务耗时比较长,比如ajax请求,如果都按照顺序进行,往往会出现浏览器无响应的情况,所以就需要异步的形式。JS中所有的任务可以分为两种:同步任务和异步任务。

  • 同步任务:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;

  • 异步任务:不进入主线程,而进入任务队列中的任务,只有任务队列通知主线程,某个异步任务可以执行了,这个任务才会进入主线程执行。

  • 事件循环(Event Loop):只有执行栈中的所有同步任务都执行完毕,系统才会读取任务队列,看看里面的异步任务哪些可以执行,然后那些对应的异步任务,结束等待状态,进入执行栈,开始执行。

CallBack

回调函数本身是我们约定俗成的一种叫法,我们定义它,但是并不会立即执行它,它最终在其他地方执行了。

  • 优点:比较容易理解;
  • 缺点:1.高耦合,维护困难,回调地狱; 2.每个任务只能指定一个回调函数; 3.如果几个异步操作之间并没有顺序之分,同样也要等待上一个操作执行结束再进行下一个操作。

回调地狱:

Promise

promise对象的构造函数语法为:

1
2
3
let promise = new Promise(function(resolve, reject) {
// executor (the producing code, "singer")
});

它的参数resolvereject是JavaScript本身提供的回调。我们的代码仅在执行程序内部。当代码执行完后,它应用调用以下回调之一:

  • resolve(value)—如果成功完成,结果为value。
  • reject(error)—如果发生错误,error则是错误对象。
Promise.then .catch .finally

Promise.then相当于执行callback,不过比起callback的嵌套模式,Promise.then().then().then()...的链式写法看起来更直观和美观。

catchfinally的用法相当于try...catch...finally

Async/Await

假如,一个页面中的很多方法都依赖于一个异步函数值的结果,又不想把写好的许多方法放到Promise.the中处理,这个时候你急切得需要一个把异步函数转换成同步函数处理的方式,这个时候async/await方法应运而生。

1
2
3
4
5
6
7
8
9
let promise = new Promise(function(resolve, reject) {
// executor (the producing code, "singer")
});
promise.then(res => {
const { data } = res;
....
}).catch(err => {
console.log(errr);
})

等价于

1
2
3
4
5
6
7
8
9
10
async function do() {
try {
const res = await promise();
const { data } = res;
...
} catch(err){
console.log(errr);
}
}