异步处理
以下代码会输出饿了
,因为setTimeout是异步处理的,相当于人家刚吃就问人家吃饱了吗
let status = '饿了';
function eat() {
setTimeout(() => {
status = '吃饱了';
}, 500);
}
eat();
console.log(status);
callback
以下代码会输出吃饱了
,因为是在状态变成吃饱了
之后才问的
let status = '饿了';
function eat(callback) {
setTimeout(() => {
status = '吃饱了';
callback && callback();
}, 500);
}
eat(() => {
console.log(status);
});
如果这个人胃口比较大,需要吃三碗才能吃饱,代码如下
let status = '饿了';
let bowl = 0;
function eat(callback) {
setTimeout(() => {
bowl++;
if (bowl >= 3) {
status = '吃饱了';
} else {
status = '没吃饱';
}
callback && callback();
}, 500);
}
eat(() => {
console.log(status);
if (status != '吃饱了') {
eat(() => {
console.log(status);
if (status != '吃饱了') {
eat(() => {
console.log(status);
})
}
})
}
});
可以发现使用回调的方式,如果碰到复杂的或者嵌套层数很多的情况,代码维护起来就很困难,这就是经典的回调地狱( callback hell )问题
promise
由于异步回调维护困难,所以es6引入了promise
let status = '饿了';
let bowl = 0;
function eat() {
return new Promise((resolve, reject) => {
setTimeout(() => {
bowl++;
if (bowl >= 3) {
status = '吃饱了';
} else {
status = '没吃饱';
}
if (Math.random() < 0.1) {
reject(new Error("撑死了"));
} else {
resolve(status);
}
}, 500);
});
}
eat().then((res) => {
console.log(res);
return eat();
}).then((res) => {
console.log(res);
return eat();
}).then((res) => {
console.log(res);
}).catch(err => {
console.log(err.message);
}).finally(() => {
console.log("不管怎样,味道还是很不错的");
});
如果同时发起多个异步任务,可以使用Promise.all()
解决异步并发问题
Promise.all()
所有都成功Promise.any()
任意一个成功Promise.race()
第一个(成功或失败都行)Promise.allSettled()
所有执行完,挑选成功的
function eat(food) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("吃了" + food);
return resolve({
food: food,
flag: Math.random()
});
}, 500);
});
}
Promise.all([eat("肉包子"), eat("菜包子"), eat("小笼包")]).then((res) => {
let winner = null;
for (let o of res) {
if (winner == null) {
winner = o;
} else if (o.flag > winner.flag) {
winner = o;
}
}
console.log(winner.food + "最好吃");
});
async/await
async/await可以让我们用同步的思维去编写异步代码
async是修饰function的关键字,async function其实是一个Promise的语法糖
const success = async function () {
return 'success';
}
const fail = async function () {
throw new Error('fail');
}
// async ƒ () { return 'success'; }
console.log(success);
// async ƒ () {return new Error('fail'); }
console.log(fail);
// Promise {<fulfilled>: 'success'}
console.log(success());
// Promise {<rejected>: Error: fail}
console.log(fail());
await是async functon中的一个关键字,用来阻止后面的代码立即执行,并且可以用同步的方法获取到Promise的执行结果
(async function () {
let status = '饿了';
await new Promise((resolve, reject) => {
setTimeout(() => {
status = '吃饱了';
resolve();
}, 500);
});
console.log(status);
}());
如果这个人胃口比较大,需要吃三碗才能吃饱,代码如下
let status = '饿了';
let bowl = 0;
function eat() {
return new Promise((resolve, reject) => {
setTimeout(() => {
bowl++;
if (bowl >= 3) {
status = '吃饱了';
} else {
status = '没吃饱';
}
if (Math.random() < 0.1) {
reject(new Error("撑死了"));
} else {
resolve(status);
}
}, 500);
});
}
(async function () {
try {
await eat();
console.log(status);
await eat();
console.log(status);
await eat();
console.log(status);
} catch (e) {
console.log(e.message);
} finally {
console.log("不管怎样,味道还是很不错的");
}
}());