回调函数(callback)
回调是一个函数被作为一个参数传递到另一个函数里,在那个函数执行完后再执行。
function f1(callback){
setTimeout(function () {
// f1的任务代码
callback();
}, 1000);
}
// 执行
f1(f2)
优点:简单、方便、实用。
缺点:易形成回调函数地狱。如果我们只有一个异步操作,用回调函数来处理是完全没有任何问题的。如果我们在回调函数中再嵌套一个回调函数,问题也不大。但是如果我们要嵌套很多个回调函数,问题就很大了,因为多个异步操作形成了强耦合,代码将乱作一团,无法管理。这种情况被称为"回调函数地狱"(callback hell)。
事件监听
监听函数有:on,bind,listen,addEventListener,observe
element.onclick=function(){
//处理函数
}
elment.attachEvent("onclick",handler1);
elment.addEvenListener("click",handler1,false);
document.getElementById("id1").addEventListener("click",function(){console.log('id1');},false);
优点:与回调函数相比,事件监听方式实现了代码的解耦,将两个回调函数分离了开来,更方便进行代码的管理。
缺点:使用起来不方便,每次都要手动地绑定和触发事件。
发布/订阅
我们假定,存在一个"信号中心",某个任务执行完成,就向信号中心"发布"(publish)一个信号,其他任务可以向信号中心"订阅"(subscribe)这个信号,从而知道什么时候自己可以开始执行。
//首先,f2向"信号中心"jQuery订阅"done"信号。
jQuery.subscribe("done", f2);
//jQuery.publish("done")的意思是,f1执行完成后,向"信号中心"jQuery发布"done"信号,从而引发f2的执行。
function f1(){
setTimeout(function () {
// f1的任务代码
jQuery.publish("done");
}, 1000);
}
//f2完成执行后,也可以取消订阅(unsubscribe)
jQuery.unsubscribe("done", f2);
promise对象(promise 模式)
(1)promise对象是commonJS工作组提出的一种规范,一种模式,目的是为了异步编程提供统一接口。
(2)promise是一种模式,promise可以帮忙管理异步方式返回的代码。他讲代码进行封装并添加一个类似于事件处理的管理层。我们可以使用promise来注册代码,这些代码会在在promise成功或者失败后运行。
(3)promise完成之后,对应的代码也会执行。我们可以注册任意数量的函数再成功或者失败后运行,也可以在任何时候注册事件处理程序。
(4)promise有两种状态:1、等待(pending);2、完成(settled)。
promise会一直处于等待状态,直到它所包装的异步调用返回/超时/结束。
(5)这时候promise状态变成完成。完成状态分成两类:1、解决(resolved);2、拒绝(rejected)。
(6)promise解决(resolved):意味着顺利结束。promise拒绝(rejected)意味着没有顺利结束。
//promise
var p=new Promise(function(resolved)){
//在这里进行处理。也许可以使用ajax
setTimeout(function(){
var result=10*5;
if(result===50){
resolve(50);
}else{
reject(new Error('Bad Math'));
}
},1000);
});
p.then(function(result){
console.log('Resolve with a values of %d',result);
});
p.catch(function(){
console.error('Something went wrong');
});
优点:使用promise的方式,我们可以成功地将回调函数变成链式调用,与前两者对比逻辑性更强,执行顺序更加清楚
缺点:代码冗余,异步操作都被包裹promise构造函数和then方法中,主题代码不明显,语义变得不清楚,编写和理解都相对比较难
优雅的async/await
async function azc() {
const data1 = await getJSON_PM('https://www.apiopen.top/weatherApi?city=广州');
const data2 = await getJSON_PM('https://www.apiopen.top/weatherApi?city=番禺');
console.log(data1, data2);
}
azc();