具有不同超时的同步回调



我正在尝试使用回调函数进行控制台,该函数本身是setTimeout函数中的回调函数。如何获得有序的结果?

我希望调用 f1 的回调,然后是 f2,最后是 f3,无论它们的计时器如何。

let f1 = (cb) => { 
setTimeout(() => {
cb(null, {a: 1})
},100)
}
let f2 = (cb) => { 
setTimeout(() => {
cb(null, {a: 2})
},50)
}
let f3 = (cb) => { 
setTimeout(() => {
cb(null, {a: 3})
},10)
}
function parallelConsole(arr, cb) {
let result = [];
arr.forEach(func => {
func((temp, val) => {
console.log(val)
result.push(val)
if(arr.length === result.length) {
cb(result)
}      
})
})
}
parallelConsole([f1, f2, f3], (res) => {
console.log(res) //[{a: 3}, {a: 2}, {a: 1}]
})

预期成果: [{a: 1}, {a:2}, {a: 3}]

实际结果: [{a: 3}, {a:2}, {a: 1}]

如果您真的必须使用回调,并且如果这是针对与生产相关的项目,那么使用 async.js 是一种选择吗?它提供了一些非常有用的功能(.each可能是您正在寻找的)。

我希望调用 f1 的回调,然后是 f2,最后是 f3,无论它们的计时器如何。

我对此有点困惑。如果超时,则在指定的时间过后将调用回调。或者,您是否希望以有序的方式(1,2,3)console.log结果,而不管何时调用回调?

编辑:我已经修复了一些你的代码,所以我认为它可以做你想要的。f1, f2, f3promise没有归还。此外,正如注释中所指出的,使用Promise.all可以确保在所有承诺都履行后调用最终回调。

const f1 = (cb) => {
return new Promise ((resolve) => setTimeout(() => {
resolve(cb(null, { a: 1 }))
}, 100))
};
const f2 = (cb) => {
return new Promise ((resolve) => setTimeout(() => {
resolve(cb(null, { a: 2 }))
}, 50))
};
const f3 = (cb) => {
return new Promise ((resolve) => setTimeout(() => {
resolve(cb(null, { a: 3 }))
}, 10))
};
function parallelConsole(arr, cb) {
return Promise.all(arr)
.then((values) => {
cb(null, values);
});
}
const log = (err, data) => {
if (err) {
// TODO: handle properly
return console.log(err);
}
return data;
};
parallelConsole([f1(log), f2(log), f3(log)], (err, res) => {
console.log(res)
});
let f1 = (cb) => {
setTimeout(() => {
cb(null, { a: 1 });
}, 100);
};
let f2 = (cb) => {
setTimeout(() => {
cb(null, { a: 2 });
}, 50);
};
let f3 = (cb) => {
setTimeout(() => {
cb(null, { a: 3 });
}, 10);
};
function parallelConsole(arr, cb) {
let result = [];
let offset = 0;
const next = () => {
if (arr.length === result.length) {
return cb(result);
}
arr[offset]((temp, val) => {
console.log(val);
result.push(val);
offset += 1;
next();
});
};
next();
}
parallelConsole([f1, f2, f3], (res) => {
console.log(res); //[{a: 3}, {a: 2}, {a: 1}]
});

如果你愿意全力以赴地使用 Promise 而不是回调,代码会变得更加优雅:

// Promisified delay. Resolves with the given optional value after msec.
const delay = (msec, value) =>
new Promise(resolve => setTimeout(() => resolve(value), msec));
// Call `cb` on the resolved value of `p`; resolve with the same value.
const tapPromise = (p, cb) =>
p.then(v => {
cb(v);
return v;
});
// Factories for the slow promises
const f1 = () => delay(100, { a: 1 });
const f2 = () => delay(50, { a: 2 });
const f3 = () => delay(10, { a: 3 });
// Create three promises and tap them with console.log.
// (They start executing right away, not when they're waited on.)
const promises = [f1(), f2(), f3()].map(p => tapPromise(p, console.log));
// Wait for all three promises to resolve, then log the results.
// Promise.all guarantees the order is the same as with the original promises.
Promise.all(promises).then(results => {
console.log(results);
});

我刚刚对您的解决方案进行了一些重构。不要使用数组推送方法,因为您需要保持输出的顺序。使用数组索引来存储结果,例如:result[index] = val;inside forEach

let f1 = (cb) => { 
setTimeout(() => {
cb(null, {a: 1})
},100)
}
let f2 = (cb) => { 
setTimeout(() => {
cb(null, {a: 2})
},50)
}
let f3 = (cb) => { 
setTimeout(() => {
cb(null, {a: 3})
},10)
}
function parallelConsole(arr, cb) {
let result = [];
arr.forEach((func, index) => {
func((temp, val) => {
result[index] = val;
if(arr.length === result.length) {
cb(result)
}      
})
})
}
parallelConsole([f1, f2, f3], (res) => {
console.log(res) //[{a: 1}, {a: 2}, {a: 3}]
})

最新更新