Javascript Node.js:无法从array.map()返回新数组

Javascript Node.js:无法从array.map()返回新数组,javascript,arrays,node.js,async-await,fs,Javascript,Arrays,Node.js,Async Await,Fs,我使用一个名为Okrabyte的包从文件夹中的每个图像文件中提取单词。结果应该是一个新的数组,其中包含可以在其他函数中使用的提取文本 当我运行此命令时: var fs = require("fs"); var okrabyte = require("okrabyte"); fs.readdir("imgs/", function(err, files){ files.map((file)=>{ okrabyte.decodeBuffer(fs.readFileSync("i

我使用一个名为Okrabyte的包从文件夹中的每个图像文件中提取单词。结果应该是一个新的数组,其中包含可以在其他函数中使用的提取文本

当我运行此命令时:

var fs = require("fs");
var okrabyte = require("okrabyte");


fs.readdir("imgs/", function(err, files){
  files.map((file)=>{
    okrabyte.decodeBuffer(fs.readFileSync("imgs/"+ file), (err, data)=>{
      let splitWords = data.split(" ");
      let word = splitWords[0].substr(1);
      console.log(word);
    })
  })
})
控制台记录每个单词。要返回包含这些单词的数组,我尝试了以下操作:

async function words() {
    await fs.readdir("imgs/", function (err, files) {
        return files.map(async (file) => {
            await okrabyte.decodeBuffer(fs.readFileSync("imgs/" + file), async (err, data) => {
                let splitWords = data.split(" ");
                let word = splitWords[0].substr(1);
                return word
            })
        })
    })
}

var testing = await words();

console.log(testing);

这给了
未定义的
我尝试过将所有内容都转换为承诺,我尝试过异步等待,我尝试过将每个单词放入一个新数组并以闭包方式返回该数组,但没有任何效果-我做错了什么???

如果你的map函数是异步的,那么它返回的是承诺,因此,映射数组实际上是一个承诺数组。但是您可以使用
Promise.all
来获得该数组的解析值

此外,您正在尝试等待调用
fs.readdir
okrabyte.decodeBuffer
,这两个函数都接受回调,并且不返回承诺。因此,如果您想在那里使用承诺,您必须手动将它们包装在承诺构造函数中

我会这样做:

async function words() {
    // Wrap `fs` call into a promise, so we can await it:
    const files = await new Promise((resolve, reject) => {
        fs.readdir("imgs/", (err, files) => { err ? reject(err) : resolve(files); });
    });

    // Since map function returns a promise, we wrap into a Promise.all:
    const mapped = await Promise.all(files.map((file) => {
        // Wrap okrabyte.decodeBuffer into promise, and return it:
        return new Promise((resolve, reject) => {
            okrabyte.decodeBuffer(fs.readFileSync("imgs/" + file), (err, data) => {
                if (err) return reject(err);
                const splitWords = data.split(" ");
                const word = splitWords[0].substr(1);
                resolve(word);
            })
        })
    }))

    // Mapped is now an array containing each "word".
    return mapped;
}

var testing = await words();

// Should now log your array of words correctly.
console.log(testing);

如果映射函数是异步的,那么它将返回一个承诺,因此映射数组实际上是一个承诺数组。但是您可以使用
Promise.all
来获得该数组的解析值

此外,您正在尝试等待调用
fs.readdir
okrabyte.decodeBuffer
,这两个函数都接受回调,并且不返回承诺。因此,如果您想在那里使用承诺,您必须手动将它们包装在承诺构造函数中

我会这样做:

async function words() {
    // Wrap `fs` call into a promise, so we can await it:
    const files = await new Promise((resolve, reject) => {
        fs.readdir("imgs/", (err, files) => { err ? reject(err) : resolve(files); });
    });

    // Since map function returns a promise, we wrap into a Promise.all:
    const mapped = await Promise.all(files.map((file) => {
        // Wrap okrabyte.decodeBuffer into promise, and return it:
        return new Promise((resolve, reject) => {
            okrabyte.decodeBuffer(fs.readFileSync("imgs/" + file), (err, data) => {
                if (err) return reject(err);
                const splitWords = data.split(" ");
                const word = splitWords[0].substr(1);
                resolve(word);
            })
        })
    }))

    // Mapped is now an array containing each "word".
    return mapped;
}

var testing = await words();

// Should now log your array of words correctly.
console.log(testing);

您将单词值返回到包含的函数,但不是map()函数

希望此代码对您有所帮助

async function words() {
    global.words = [];
    await fs.readdir("imgs/", function(err, files){
      return files.map( async(file)=>{
        await okrabyte.decodeBuffer(fs.readFileSync("imgs/"+ file), async (err, data)=>{
          let splitWords = data.split(" ");
          let word = splitWords[0].substr(1);
          global.words.push(word);
        })
      })
    })
  }

  var testing = await words();
  testing = global.words;
  console.log(testing);

您将单词值返回到包含的函数,但不是map()函数

希望此代码对您有所帮助

async function words() {
    global.words = [];
    await fs.readdir("imgs/", function(err, files){
      return files.map( async(file)=>{
        await okrabyte.decodeBuffer(fs.readFileSync("imgs/"+ file), async (err, data)=>{
          let splitWords = data.split(" ");
          let word = splitWords[0].substr(1);
          global.words.push(word);
        })
      })
    })
  }

  var testing = await words();
  testing = global.words;
  console.log(testing);

您不应该以这种方式使用异步等待。当你处理承诺时,应该使用这一点。库okrabyte使用回调的概念

我建议您遵循以下方法:

(1) 将okrabyte.decodeBuffer部分包含在一个函数中,该函数返回在回调中解析的承诺

(2) 使用files.map生成一个承诺数组,以调用(1)中定义的函数

(3) 使用Promise.all等待所有承诺执行并完成,然后再继续处理所有单词

演练:

第1部分

const processWord = (file) => {
  return new Promise((resolve, reject) => {
    okrabyte.decodeBuffer(fs.readFileSync("imgs/"+ file), (err, data)=>{
      if (err) {
        reject(err); // <--- reject the promise if there was an error
        return;
      }

      let splitWords = data.split(" ");
      let word = splitWords[0].substr(1);
      resolve(word); // <--- resolve the promise with the word
    })
  });
}
上述内容将产生一系列承诺

第三部分

fs.readdir("imgs/", function(err, files){
  const promises = files.map((file)=>{
    return processWord(file);
  })

  Promise.all(promises)
    .then(responses => {
      // responses holds a list of words
      // You will get each word accessing responses[0], responses[1], responses[2], ...
      console.log(responses);
    })
    .catch(error => {
      console.log(error); // Deal with the error in some way
    });
})
上面使用Promise.all在转到then()块之前等待所有承诺的解析,假设没有发生错误

您可以在一个方法中进一步隔离上面的构造,该方法将返回一个包含所有单词列表的承诺,其方式与第1部分的processWord函数中的方式大致相同。这样,如果愿意,您最终可以使用async Wait,而不是在then()块中处理事情:


您不应该以这种方式使用异步等待。当你处理承诺时,应该使用这一点。库okrabyte使用回调的概念

我建议您遵循以下方法:

(1) 将okrabyte.decodeBuffer部分包含在一个函数中,该函数返回在回调中解析的承诺

(2) 使用files.map生成一个承诺数组,以调用(1)中定义的函数

(3) 使用Promise.all等待所有承诺执行并完成,然后再继续处理所有单词

演练:

第1部分

const processWord = (file) => {
  return new Promise((resolve, reject) => {
    okrabyte.decodeBuffer(fs.readFileSync("imgs/"+ file), (err, data)=>{
      if (err) {
        reject(err); // <--- reject the promise if there was an error
        return;
      }

      let splitWords = data.split(" ");
      let word = splitWords[0].substr(1);
      resolve(word); // <--- resolve the promise with the word
    })
  });
}
上述内容将产生一系列承诺

第三部分

fs.readdir("imgs/", function(err, files){
  const promises = files.map((file)=>{
    return processWord(file);
  })

  Promise.all(promises)
    .then(responses => {
      // responses holds a list of words
      // You will get each word accessing responses[0], responses[1], responses[2], ...
      console.log(responses);
    })
    .catch(error => {
      console.log(error); // Deal with the error in some way
    });
})
上面使用Promise.all在转到then()块之前等待所有承诺的解析,假设没有发生错误

您可以在一个方法中进一步隔离上面的构造,该方法将返回一个包含所有单词列表的承诺,其方式与第1部分的processWord函数中的方式大致相同。这样,如果愿意,您最终可以使用async Wait,而不是在then()块中处理事情:


看似足够简洁的狂热解决方案/解释-谢谢!看似足够简洁的狂热解决方案/解释-谢谢!这也是一个非常棒的演练,谢谢!我选择另一个答案是因为它简单明了。这也是一个非常好的演练谢谢!我选择了另一个答案,因为它简单明了。不幸的是,这不起作用,因为我们使用的是map(),所以我想利用map()生成的数组,而不是创建一个额外的数组并将元素推送到其中。不幸的是,这不起作用,因为我们使用的是map(),所以我想利用map()生成的数组而不是创建一个额外的数组并将元素推送到它。