如何从外部函数访问数组?

时间:2016-11-27 19:07:13

标签: javascript node.js asynchronous ecmascript-6

我是异步编程的新手

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) => { });内推送的内容,以便我可以从外部函数中访问它?

3 个答案:

答案 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)

您可以使用Promisesasync 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来转换代码。