我是异步编程的新手
function loadPlugin(plugins, callback) {
let tests = [[], [], []];
plugins.forEach((plugin) => {
f.isPlugin(plugin, (exists) => {
if (exists) {
if (!f.pluginIsLoaded(plugin)) {
tests[0].push(plugin);
f.loadPlugin(plugin);
} else {
tests[1].push(plugin);
}
} else {
tests[2].push(plugin);
}
});
console.log(tests);
});
return tests;
}
和
module.exports.isPlugin = (plugin , callback) => {
fs.access(`./plugins/${plugin}`, fs.constants.F_OK, (err) => {
callback(!err);
});
};
在f.isPlugin(plugin, (exists) => { });
内部我将plugin
推入tests
数组,并从外部函数推送console.log(tests)
,表明tests
数组是一个包含3的数组其中有空数组。
有没有办法可以保留f.isPlugin(plugin, (exists) => { });
内推送的内容,以便我可以从外部函数中访问它?
答案 0 :(得分:2)
您可以从回调模式切换到promises并使用Promise.all
等待所有插件检查完成:
module.exports.isPlugin = plugin => new Promise( resolve =>
fs.access(`./plugins/${plugin}`, fs.constants.F_OK, err => resolve(!err))
);
function loadPlugin(plugins) {
let tests = [[], [], []];
let promises = plugins.map( plugin =>
f.isPlugin(plugin).then( exists => {
let status = !exists ? 2 : +f.pluginIsLoaded(plugin);
if (!status) f.loadPlugin(plugin);
tests[status].push(plugin);
})
);
// Turn the array of promises into one promise,
// which provides the tests array when it resolves:
return Promise.all(promises).then( _ => tests );
}
所以你会把它称为:
loadPlugin(plugins).then( tests => console.log(tests) );
答案 1 :(得分:1)
您无法通过回调函数返回某些内容,您必须使用结果调用回调函数。这不是访问数组的问题,在任何有机会被推送之前正在打印数组。如果你喜欢回归(这应该是很有意义的)我建议使用promises。阅读承诺here。我刚刚使用回调做出了回答,但我意识到每次都不会有效。说实话,我不知道如何用回调来做到这一点。这是Promises的解决方案。
function loadPlugin(plugins) {
let tests = [[], [], []];
// This maps your array to a promise for each one that resolves when the task is complete
let promises = plugins.map((plugin) => {
return new Promise((resolve, reject) => {
f.isPlugin(plugin, (exists) => {
if (exists) {
if (!f.pluginIsLoaded(plugin)) {
tests[0].push(plugin);
f.loadPlugin(plugin);
} else {
tests[1].push(plugin);
}
} else {
tests[2].push(plugin);
}
// Tells the promise the task is complete
resolve();
});
});
});
// Wait for all of the tasks to complete then return tests
return Promise.all(promises).then(() => tests);
}
@Gothdo的解决方案更好,但我不确定您是否使用转换器来使用async await语法。我建议这样做并继续他/她的解决方案。
答案 2 :(得分:1)
您可以使用Promises和async functions。
首先,更改isPlugin
函数以返回Promise
:
module.exports.isPlugin = plugin => new Promise(resolve =>
fs.access(`./plugins/${plugin}`, fs.constants.F_OK, err => resolve(!err))
);
然后将loadPlugin
函数更改为异步函数:
async function loadPlugin(plugins) {
let tests = [[], [], []];
for (const plugin of plugins) {
const exists = await f.isPlugin(plugin);
if (exists) {
if (!f.pluginIsLoaded(plugin)) {
tests[0].push(plugin);
f.loadPlugin(plugin);
} else {
tests[1].push(plugin);
}
} else {
tests[2].push(plugin);
}
}
return tests;
}
请注意,Node.js尚不支持异步函数,因此您必须使用Babel来转换代码。