异步遍历
doDuring
- 直到第二个参数test函数返回true时,停止循环,触发callback
基本使用
nac.doDuring(
function (callback) {
setTimeout(function () {
console.log('end');
index++;
callback(null); // 作用是触发和传递参数给test
}, 1000);
},
function (callback) {// test函数,返回true时停止任务,触发下一个callback
callback(null, index!==3);
},
function (err) {
if (err) {
console.error(err);
} else {
console.log('done');
}
}
);
实现:
function doDuring(iterator, test, callback) {
callback = callback || noop;
iterate(null, true);
// iterate->iterator->iterate
function iterate(err, truth) {
if (err) {
return callback(err);
}
if (truth) {
iterator(done);
} else {
callback(null);
}
}
function done(err, res) {
if (err) {
return callback(err);
}
switch (arguments.length) {
case 0:
case 1:
test(iterate);
break;
case 2:
test(res, iterate);
break;
default:
var args = slice(arguments, 1);
args.push(iterate);
test.apply(null, args);
break;
}
}
}
doUntil
- 和doDuring的区别是,通过test函数返回值来判断是否终止循环
基本使用
let count = 0;
nac.doUntil(
(callback) => {
count++;
callback(null, count); // 触发test函数
},
(count) => {
return count === 5;
},
(err, result) => {
console.log(result);
}
);
实现:
function doUntil(iterator, test, callback) {
callback = callback || noop;
var sync = false;
next();
function iterate() {
if (sync) {
nextTick(next); // 避免同步任务阻塞
} else {
sync = true;
iterator(done);
}
sync = false;
}
function next() {
iterator(done);
}
function done(err, arg) {
if (err) {
return callback(err);
}
if (arguments.length <= 2) {
if (!test(arg)) {
iterate();
} else {
callback(null, arg);
}
return;
}
arg = slice(arguments, 1);
if (!test.apply(null, arg)) {
iterate();
} else {
callback.apply(null, [null].concat(arg));
}
}
}