遍历和迭代是很类似的两个概念,遍历就是在一个东西内循环的拿数据,而迭代则是在遍历的过程中进行一次程序上的输出,也就是说迭代是遍历的一个步骤。
写一个生成器函数:
var arr = [1, 2, 3, 4, 5, 6];
function* test() {
for (const iterator of arr) {
// yield 具有停止的作用
yield iterator;
}
}
// iter 就是一个迭代器 iterator
let iter = test();
// 迭代器具有 next 方法,返回本次迭代的数据
console.log(iter.next()); // {value: 1, done: false}
console.log(iter.next()); // {value: 2, done: false}
假如现在有一个需求,有 5 个函数需要依次执行,改怎么做呢?当然你肯定想到遍历执行。
var functions = [
function test1() {
console.log("test1");
},
function test2() {
console.log("test2");
},
function test3() {
console.log("test3");
},
function test4() {
console.log("test4");
},
function test5() {
console.log("test5");
}
];
for (const iterator of functions) {
iterator();
}
// test1
// test2
// test3
// test4
// test5
那么我想在执行完test3
的时候停止执行又该怎么办呢?首先想到的肯定是break
,但是怎么知道执行到test3
函数呢?要不给函数加个返回布尔值试试。
var functions = [
function test1() {
console.log("test1");
return true;
},
function test2() {
console.log("test2");
return true;
},
function test3() {
console.log("test3");
return false;
},
function test4() {
console.log("test4");
return true;
},
function test5() {
console.log("test5");
return true;
}
];
for (const iterator of functions) {
if (!iterator()) break;
}
// test1
// test2
// test3
这样就实现了函数执行的中止操作。
在NodeJS
中有个东西叫做「中间件」。假如有个需求用户访问/user
页面的时候需要进行一系列的判断,如果某个判断存在问题需要跳转到登录页
这个时候如果还使用return false
就不合适了,可以利用Koa
中间件函数中的next
方法,当调用next
方法后再继续执行后面的函数。
var functions = [
function test1(next) {
console.log("test1");
next();
},
function test2(next) {
console.log("test2");
next();
},
function test3(next) {
console.log("test3");
// 假如判断是否有 token
if (true) {
next();
}
},
function test4(next) {
console.log("test4");
next();
},
function test5(next) {
console.log("test5");
next();
},
];
(function (functions) {
// 生成器函数
function* generator(arr) {
for (const iterator of arr) {
yield iterator;
}
}
const iter = generator(functions);
const init = () => {
nextDo(iter.next());
};
// 第一次执行,n 等于 {value: fun, done: false}
// 然后执行第 4 行的 next(),相当于这里的匿名函数执行
// 匿名函数执行,会继续进行迭代,然后再判断...
function nextDo(n) {
n.value(function () {
const n = iter.next();
if (!n.done) {
nextDo(n);
} else {
return;
}
});
}
init();
})(functions);