乐趣区

循环中调用异步方法

课程视频 – 循环中调用异步方法
最近遇到一道比较有趣的面试题,题目很简单但是涉及到了很多小的知识点,还蛮有意思的。
一个普通的 for 循环输出 i
// 正常写一个 for 循环输出 i
for (var i = 0; i < 5; i++) {
console.log(i);
}
console.log(i);
假设你是一个面试者,你说说这几行代码会输出什么?,你的内心活动会不会是“这特么不就是一个循环吗?面试官既然这么问老子(他还笑肯定不是好东西,肯定有陷阱),好好想一下,这好像和我看的那个闭包的题很像啊,这面试官是不是没写完啊?怎么办。”
如果稍微改动一些尼,输出结果又是什么?
for 循环中有一个定时器
for (var i = 0; i < 5; i++) {
setTimeout(function () {
console.log(new Date, i);
}1000 * i);
}
console.log(new Date, i);
稍微加了点料 (setTimeout) 后,是不是看到这道题就舒服了,会不会想“’这不是老子背的最多的闭包问题么,想一哈,setTimeout 是会延迟执行的所以外面的 log 会先执行,i 是用 var 声明的,所以会变量提升,for 循环里 i 最后执行完 i ++,i 变成了 5,没错了,老子这题得分了”。
闭包解决。
// 闭包
for (var i = 0; i < 5; i++) {
~function (j) {
setTimeout(function () {
console.log(new Date, j);
}, 1000 * j);
}(i);
}
顺着上一个程式想“是不是还可以升华一下,我还能执行出来 0 1 2 3 4”
实作
var roles = [‘ 角色 1 ’, ‘ 角色 2 ’, ‘ 角色 3 ’];
var arrayTest = [];
for (var i = 0; i < roles.length; i++) {
!function (i) {
$.get(‘https://www.baidu.com’, { role: roles[i] }, function (res) {
console.log(i);
arrayTest[i] = i + roles[i] + res;
})
}(i);
}
如果你登录一个后台系统,这个账号下有不同角色(角色不固定,后期可能增加),传不同角色进行 ajax 请求得到相应渲染页面的数据,但是这个接口只接收一个角色参数,那我们应该怎么按我们想要的顺序获取数据然后渲染页面?
es6
const tasks = [];
for (var i = 0; i < 5; i++) {
((j) => {
tasks.push(new Promise((resolve) => {
setTimeout(() => {
console.log(new Date, j);
resolve();
}, 1000 * j); // 定时器的超时时间逐步增加
}));
})(i);
}

Promise.all(tasks).then(() => {
setTimeout(() => {
console.log(new Date, i);
}, 1000);
});
当你前面所有问题都顺利的回答完了,你想没想过可能还有 20% 的人可以回答到你这种程度,怎么能变现的比他们牛逼一点尼?你可以考虑使用一下 promise
setTimeout 和 promise 优先级
setTimeout(function () {
console.log(1)
}, 0);
new Promise(function executor(resolve) {
console.log(2);
for (var i = 0; i < 10000; i++) {
i == 9999 && resolve();
}
console.log(3);
}).then(function () {
console.log(4);
});
console.log(5);
“这道题应该考察我 JavaScript 的运行机制的,让我理一下思路。
首先先碰到一个 setTimeout,于是会先设置一个定时,在定时结束后将传递这个函数放到任务队列里面,因此开始肯定不会输出 1。
然后是一个 Promise,里面的函数是直接执行的,因此应该直接输出 2 3。
然后,Promise 的 then 应当会放到当前 tick 的最后,但是还是在当前 tick 中。
因此,应当先输出 5,然后再输出 4。
最后在到下一个 tick,就是 1。
“2 3 5 4 1”
es7
const sleep = (timeountMS) => new Promise((resolve) => {
setTimeout(resolve, timeountMS);
});

(async () => {// 声明即执行的 async 函数表达式
for (var i = 0; i < 5; i++) {
await sleep(1000);
console.log(new Date, i);
}

await sleep(1000);
console.log(new Date, i);
})();

要是想给面试官留一个关注新技术的更牛逼印象,那就用 es7 说一下吧。

原始高清视频下载
视频讲解 – 提取码: ifv9
QQ 答疑交流群: 600633658
我们的链接:
知乎 掘金 今日头条 新浪微博 前端网 思否 简书 B 站

退出移动版