Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/477.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript for循环完成添加到数组后返回结果_Javascript_Node.js_Asynchronous - Fatal编程技术网

Javascript for循环完成添加到数组后返回结果

Javascript for循环完成添加到数组后返回结果,javascript,node.js,asynchronous,Javascript,Node.js,Asynchronous,我试图在forEach循环完成向其添加项后返回一个数组。我尝试了几种方法,但它们要么返回空数组,要么返回未解决的承诺 我的代码 给班级打电话 文件只是一个字符串,不是承诺,所以不需要解析它。fs.readdir返回一个承诺,因此它可以与.then一起使用。进程退出时,中间promiseFiles和promiseFolders将为空,但不需要它们,因为文件不是承诺。您的原始实现存在几个计时问题。您的.forEach循环不会等待其中的任何异步操作完成,因此您最终会在填充数组之前调用Promise.a

我试图在forEach循环完成向其添加项后返回一个数组。我尝试了几种方法,但它们要么返回空数组,要么返回未解决的承诺

我的代码 给班级打电话


文件只是一个字符串,不是承诺,所以不需要解析它。fs.readdir返回一个承诺,因此它可以与.then一起使用。进程退出时,中间promiseFiles和promiseFolders将为空,但不需要它们,因为文件不是承诺。

您的原始实现存在几个计时问题。您的.forEach循环不会等待其中的任何异步操作完成,因此您最终会在填充数组之前调用Promise.all。我建议使用具有内置promise支持的fs操作,并在fs.promises.readdir中使用withFileTypes选项:

注意:此实现有点奇怪,因为它同时填充this.promiseFiles和this.promiseFolders,并返回解析为包含该数据的对象的承诺。我真的建议你做一个或另一个。此外,由于添加到this.promiseFiles和this.promiseFolders的这种副作用编程,如果您多次调用getFilesAndFolders,它将创建重复项

也许您根本不需要实例数据中的这些数据,该方法只需返回一个承诺即可解析为对象:

class handleFiles {
  constructor() {
  }
  async fillFilesAndFolders() {
      const sendFiles = [], sendFolders = [];
      let files = await fs.promises.readdir("uploads", {withFileTypes: true});
      for (let file of files) {
          if (file.isFile()) {
              sendFiles.push(file.name);
          } else if (file.isDirectory()) {
              sendFolders.push(file.name);
          }
      }
      return {
          sendFiles,
          sendFolders
      };
  }
}
但是,现在这只是一个静态方法,实际上与类没有任何关系,所以它可能只是一个独立的函数或静态方法

第二个解决方案中的分步说明:

声明本地变量promiseFolders和PromiseFile。 调用wait fs.promises.readdir,以便我们可以使用readdir的promise接口。 传递withFileTypes选项,这样我们就可以访问isFile和isDirectory,而无需对每个文件进行额外调用。 遍历文件列表,并用文件名填充所需的promiseFiles或promiseFolders数组。 构建返回的数据结构并返回它,它将是从父异步函数返回的承诺的解析值。
Readdir返回一个承诺,这样您就可以等待fs.Readdir…@Charles Bamford我正在尝试将其分为文件和文件夹。returnFilesAndFolders返回一个包含两个承诺的数组。数组没有then方法。let combined={在你的数组被填充之前发生。它需要在之后发生。提示readdir并等待它或返回承诺。提示readdir并等待它或返回它小心不要将readdir的回调版本与承诺版本@Charles Bamford混合,这似乎返回未定义?@Kevin B你知道为什么这段代码是r吗eturning未定义?是,fs.readdiruploads,错误,files=>{不返回任何内容。请参阅上面的文档。这不会从returnFilesAndFolders函数返回任何内容。它只会从fs.readdir回调返回一些内容,这些内容不会返回到fs模块的内部,在那里被忽略。非常感谢,您的第二个解决方案是我最初的要求,我将其转换为函数1.你介意解释一下事情的顺序吗happening@rishi-我添加了一个分步描述。非常感谢,但是我仍然不明白为什么您的返回在for循环之后运行,而在我的代码中没有。@rishi-您的.forEach循环中有异步操作。该循环不会因这些异步操作而暂停-它是ust并行启动它们,循环完成,然后异步操作在一段时间后完成。我正在使用wait和一个返回承诺的异步操作,我在循环中没有异步操作。@rishi-在循环中可以有异步操作,但如果希望循环等待它们,您必须使用普通的for或while循环,并且必须将wait用于返回承诺的异步操作。forEach不支持承诺,因此无法用于对承诺进行排序。事实上,我认为,.forEach现在基本上应该被弃用,因为for循环给您提供了更多的控制,我们有块作用域,而这都是m对于异步操作更是如此。同样,for循环也可以通过解释器进行更优化。
app.get("/:dir?", (req, res) => {
  let dir = req.params.dir;
  console.log(dir);
  let fileHandler = new handleFiles();

  fileHandler.returnFilesAndFolders().then((data) => {
    console.log(data);
    res.render("index", {
      data: data,
    });
  });
});
async returnFilesAndFolders() {
  // Return the fs.readdir promise.
  return fs.readdir("uploads").then((files) => {

    // Collect the files into files and folders.
    return files.reduce((acc, file) => {
      // Get the status of the file.
      const stat = fs.statSync(path.resolve(`uploads/${file}`));

      if (stat.isFile()) {
        acc.sendFiles.push(file);
      }
      elseif (stat.isDirectory()) {
        acc.sendFolders.push(file);
      }

      return acc;
    }, {sendFiles: [], sendFolders: []})
  });
}
class handleFiles {
  constructor() {
    this.promiseFiles = [];
    this.promiseFolders = [];
  }
  async getFilesAndFolders() {
      let files = await fs.promises.readdir("uploads", {withFileTypes: true});
      for (let file of files) {
          if (file.isFile()) {
              this.promiseFiles.push(file.name);
          } else if (file.isDirectory()) {
              this.promiseFolders.push(file.name);
          }
      }
      return {
          sendFiles: this.promiseFiles,
          sendFolders: this.promiseFolders
      }
  }
}
class handleFiles {
  constructor() {
  }
  async fillFilesAndFolders() {
      const sendFiles = [], sendFolders = [];
      let files = await fs.promises.readdir("uploads", {withFileTypes: true});
      for (let file of files) {
          if (file.isFile()) {
              sendFiles.push(file.name);
          } else if (file.isDirectory()) {
              sendFolders.push(file.name);
          }
      }
      return {
          sendFiles,
          sendFolders
      };
  }
}