Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/35.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 在forEach循环中使用async/await_Javascript_Node.js_Promise_Async Await_Ecmascript 2017 - Fatal编程技术网

Javascript 在forEach循环中使用async/await

Javascript 在forEach循环中使用async/await,javascript,node.js,promise,async-await,ecmascript-2017,Javascript,Node.js,Promise,Async Await,Ecmascript 2017,在forEach循环中使用async/wait是否存在任何问题?我试图循环浏览一系列文件,并等待每个文件的内容 import fs from 'fs-promise' async function printFiles () { const files = await getFilePaths() // Assume this works fine files.forEach(async (file) => { const contents = await fs.rea

forEach
循环中使用
async
/
wait
是否存在任何问题?我试图循环浏览一系列文件,并等待每个文件的内容

import fs from 'fs-promise'

async function printFiles () {
  const files = await getFilePaths() // Assume this works fine

  files.forEach(async (file) => {
    const contents = await fs.readFile(file, 'utf8')
    console.log(contents)
  })
}

printFiles()

这段代码确实有效,但会不会出问题?有人告诉我,在这样的高阶函数中,不应该使用
async
/
wait
,所以我只想问一下这是否有任何问题。

确定代码确实有效,但我非常确定它没有达到您期望的效果。它只是触发了多个异步调用,但是
printFiles
函数会立即返回

顺序阅读 如果要按顺序读取文件,实际上不能使用
forEach
。只需使用一个现代的
for…of
循环,其中
wait
将按预期工作:

async function printFiles () {
  const files = await getFilePaths();

  for (const file of files) {
    const contents = await fs.readFile(file, 'utf8');
    console.log(contents);
  }
}
并行阅读 如果要并行读取文件,实际上不能使用
forEach
。每一个
async
回调函数调用都会返回一个承诺,但是您将它们扔掉而不是等待它们。只需使用
map
,您就可以等待
Promise带来的一系列承诺。所有

async function printFiles () {
  const files = await getFilePaths();

  await Promise.all(files.map(async (file) => {
    const contents = await fs.readFile(file, 'utf8')
    console.log(contents)
  }));
}

当然,代码确实有效,但我非常确定它没有达到您期望的效果。它只是触发了多个异步调用,但是
printFiles
函数会立即返回

顺序阅读 如果要按顺序读取文件,实际上不能使用
forEach
。只需使用一个现代的
for…of
循环,其中
wait
将按预期工作:

async function printFiles () {
  const files = await getFilePaths();

  for (const file of files) {
    const contents = await fs.readFile(file, 'utf8');
    console.log(contents);
  }
}
并行阅读 如果要并行读取文件,实际上不能使用
forEach
。每一个
async
回调函数调用都会返回一个承诺,但是您将它们扔掉而不是等待它们。只需使用
map
,您就可以等待
Promise带来的一系列承诺。所有

async function printFiles () {
  const files = await getFilePaths();

  await Promise.all(files.map(async (file) => {
    const contents = await fs.readFile(file, 'utf8')
    console.log(contents)
  }));
}
npm上的模块实现了数组迭代方法,因此它们可以以非常简单的方式与async/await一起使用

您的案例示例如下:

const { forEach } = require('p-iteration');
const fs = require('fs-promise');

(async function printFiles () {
  const files = await getFilePaths();

  await forEach(files, async (file) => {
    const contents = await fs.readFile(file, 'utf8');
    console.log(contents);
  });
})();
npm上的模块实现了数组迭代方法,因此它们可以以非常简单的方式与async/await一起使用

您的案例示例如下:

const { forEach } = require('p-iteration');
const fs = require('fs-promise');

(async function printFiles () {
  const files = await getFilePaths();

  await forEach(files, async (file) => {
    const contents = await fs.readFile(file, 'utf8');
    console.log(contents);
  });
})();

然而,上述两种解决方案都能起作用,Antonio的代码更少,下面是它如何帮助我从数据库中解析数据,从几个不同的子引用中解析数据,然后将它们全部推到一个数组中,并在完成所有操作后以承诺的方式解析数据:

Promise.all(PacksList.map((pack)=>{
    return fireBaseRef.child(pack.folderPath).once('value',(snap)=>{
        snap.forEach( childSnap => {
            const file = childSnap.val()
            file.id = childSnap.key;
            allItems.push( file )
        })
    })
})).then(()=>store.dispatch( actions.allMockupItems(allItems)))

然而,上述两种解决方案都能起作用,Antonio的代码更少,下面是它如何帮助我从数据库中解析数据,从几个不同的子引用中解析数据,然后将它们全部推到一个数组中,并在完成所有操作后以承诺的方式解析数据:

Promise.all(PacksList.map((pack)=>{
    return fireBaseRef.child(pack.folderPath).once('value',(snap)=>{
        snap.forEach( childSnap => {
            const file = childSnap.val()
            file.id = childSnap.key;
            allItems.push( file )
        })
    })
})).then(()=>store.dispatch( actions.allMockupItems(allItems)))

在一个文件中弹出几个方法将以序列化顺序处理异步数据,并为您的代码提供更传统的风格,这是非常轻松的。例如:

module.exports = function () {
  var self = this;

  this.each = async (items, fn) => {
    if (items && items.length) {
      await Promise.all(
        items.map(async (item) => {
          await fn(item);
        }));
    }
  };

  this.reduce = async (items, fn, initialValue) => {
    await self.each(
      items, async (item) => {
        initialValue = await fn(initialValue, item);
      });
    return initialValue;
  };
};
现在,假设保存在“./myAsync.js”中,您可以在相邻文件中执行类似于以下操作:

...
/* your server setup here */
...
var MyAsync = require('./myAsync');
var Cat = require('./models/Cat');
var Doje = require('./models/Doje');
var example = async () => {
  var myAsync = new MyAsync();
  var doje = await Doje.findOne({ name: 'Doje', noises: [] }).save();
  var cleanParams = [];

  // FOR EACH EXAMPLE
  await myAsync.each(['bork', 'concern', 'heck'], 
    async (elem) => {
      if (elem !== 'heck') {
        await doje.update({ $push: { 'noises': elem }});
      }
    });

  var cat = await Cat.findOne({ name: 'Nyan' });

  // REDUCE EXAMPLE
  var friendsOfNyanCat = await myAsync.reduce(cat.friends,
    async (catArray, friendId) => {
      var friend = await Friend.findById(friendId);
      if (friend.name !== 'Long cat') {
        catArray.push(friend.name);
      }
    }, []);
  // Assuming Long Cat was a friend of Nyan Cat...
  assert(friendsOfNyanCat.length === (cat.friends.length - 1));
}

在一个文件中弹出几个方法将以序列化顺序处理异步数据,并为您的代码提供更传统的风格,这是非常轻松的。例如:

module.exports = function () {
  var self = this;

  this.each = async (items, fn) => {
    if (items && items.length) {
      await Promise.all(
        items.map(async (item) => {
          await fn(item);
        }));
    }
  };

  this.reduce = async (items, fn, initialValue) => {
    await self.each(
      items, async (item) => {
        initialValue = await fn(initialValue, item);
      });
    return initialValue;
  };
};
现在,假设保存在“./myAsync.js”中,您可以在相邻文件中执行类似于以下操作:

...
/* your server setup here */
...
var MyAsync = require('./myAsync');
var Cat = require('./models/Cat');
var Doje = require('./models/Doje');
var example = async () => {
  var myAsync = new MyAsync();
  var doje = await Doje.findOne({ name: 'Doje', noises: [] }).save();
  var cleanParams = [];

  // FOR EACH EXAMPLE
  await myAsync.each(['bork', 'concern', 'heck'], 
    async (elem) => {
      if (elem !== 'heck') {
        await doje.update({ $push: { 'noises': elem }});
      }
    });

  var cat = await Cat.findOne({ name: 'Nyan' });

  // REDUCE EXAMPLE
  var friendsOfNyanCat = await myAsync.reduce(cat.friends,
    async (catArray, friendId) => {
      var friend = await Friend.findById(friendId);
      if (friend.name !== 'Long cat') {
        catArray.push(friend.name);
      }
    }, []);
  // Assuming Long Cat was a friend of Nyan Cat...
  assert(friendsOfNyanCat.length === (cat.friends.length - 1));
}

一个重要的警告是:
wait+for。。方法和forEach+async方法实际上有不同的效果

在real
for
循环中使用
wait
将确保逐个执行所有异步调用。而
forEach+async
方式将同时发出所有承诺,速度更快,但有时会不知所措(如果您执行一些数据库查询或访问一些具有音量限制的web服务,并且不希望一次发出100000个呼叫)

如果您不使用
async/await
并希望确保文件被一个接一个地读取,您也可以使用
reduce+promise
(不太优雅)

files.reduce((lastPromise, file) => 
 lastPromise.then(() => 
   fs.readFile(file, 'utf8')
 ), Promise.resolve()
)
也可以创建forEachAsync来提供帮助,但基本上对底层循环使用相同的方法

Array.prototype.forEachAsync = async function(cb){
    for(let x of this){
        await cb(x);
    }
}

一个重要的警告是:
wait+for。。方法和forEach+async方法实际上有不同的效果

在real
for
循环中使用
wait
将确保逐个执行所有异步调用。而
forEach+async
方式将同时发出所有承诺,速度更快,但有时会不知所措(如果您执行一些数据库查询或访问一些具有音量限制的web服务,并且不希望一次发出100000个呼叫)

如果您不使用
async/await
并希望确保文件被一个接一个地读取,您也可以使用
reduce+promise
(不太优雅)

files.reduce((lastPromise, file) => 
 lastPromise.then(() => 
   fs.readFile(file, 'utf8')
 ), Promise.resolve()
)
也可以创建forEachAsync来提供帮助,但基本上对底层循环使用相同的方法

Array.prototype.forEachAsync = async function(cb){
    for(let x of this){
        await cb(x);
    }
}

我会使用经过良好测试的(每周数百万次下载)和模块。如果您不熟悉异步模块,我强烈建议您检查一下。我见过多个开发人员浪费时间重新创建其方法,或者更糟的是,当高阶异步方法简化代码时,很难维护异步代码

const async=require('async'))
常量fs=require('fs-promise')
const pify=require('pify')
异步函数getFilePath(){
还愿([
“./package.json”,
“./package lock.json”,
]);
}
异步函数printFiles(){
const files=await getfilepath()
等待pify(async.eachSeries)(文件,异步
async function printFiles () {
  const files = await getFilePaths()

  for await (const contents of files.map(file => fs.readFile(file, 'utf8'))) {
    console.log(contents)
  }
}
const AsyncAF = require('async-af');
const fs = require('fs-promise');

function printFiles() {
  // since AsyncAF accepts promises or non-promises, there's no need to await here
  const files = getFilePaths();

  AsyncAF(files).forEach(async file => {
    const contents = await fs.readFile(file, 'utf8');
    console.log(contents);
  });
}

printFiles();
const AsyncAF = require('async-af');
const fs = require('fs-promise');

function printFiles() {
  const files = getFilePaths();

  AsyncAF(files).forEach(file => {
    AsyncAF.log(fs.readFile(file, 'utf8'));
  });
}

printFiles();
const aaf = require('async-af');
const fs = require('fs-promise');

const printFiles = () => aaf(getFilePaths())
  .map(file => fs.readFile(file, 'utf8'))
  .forEach(file => aaf.log(file));

printFiles();
// Example of asyncForEach Array poly-fill for NodeJs
// file: asyncForEach.js
// Define asynForEach function 
async function asyncForEach(iteratorFunction){
  let indexer = 0
  for(let data of this){
    await iteratorFunction(data, indexer)
    indexer++
  }
}
// Append it as an Array prototype property
Array.prototype.asyncForEach = asyncForEach
module.exports = {Array}
// Nodejs style
// file: someOtherFile.js

const readline = require('readline')
Array = require('./asyncForEach').Array
const log = console.log

// Create a stream interface
function createReader(options={prompt: '>'}){
  return readline.createInterface({
    input: process.stdin
    ,output: process.stdout
    ,prompt: options.prompt !== undefined ? options.prompt : '>'
  })
}
// Create a cli stream reader
async function getUserIn(question, options={prompt:'>'}){
  log(question)
  let reader = createReader(options)
  return new Promise((res)=>{
    reader.on('line', (answer)=>{
      process.stdout.cursorTo(0, 0)
      process.stdout.clearScreenDown()
      reader.close()
      res(answer)
    })
  })
}

let questions = [
  `What's your name`
  ,`What's your favorite programming language`
  ,`What's your favorite async function`
]
let responses = {}

async function getResponses(){
// Notice we have to prepend await before calling the async Array function
// in order for it to function as expected
  await questions.asyncForEach(async function(question, index){
    let answer = await getUserIn(question)
    responses[question] = answer
  })
}

async function main(){
  await getResponses()
  log(responses)
}
main()
// Should prompt user for an answer to each question and then 
// log each question and answer as an object to the terminal
async function asyncMap(iteratorFunction){
  let newMap = []
  let indexer = 0
  for(let data of this){
    newMap[indexer] = await iteratorFunction(data, indexer, this)
    indexer++
  }
  return newMap
}

Array.prototype.asyncMap = asyncMap
const result = await Promise.all(filePaths
    .map( async filePath => {
      const fileContents = await getAssetFromCache(filePath, async function() {

        // 1. Wrap with Promise    
        // 2. Return the result of the Promise
        return await new Promise((res, rej) => {
          fs.readFile(filePath, 'utf8', function(err, data) {
            if (data) {
              res(data);
            }
          });
        });
      });

      return fileContents;
    }));
TypeError [ERR_INVALID_CALLBACK]: Callback must be a function
await (()=>{
     return new Promise((resolve,reject)=>{
       items.forEach(async (item,index)=>{
           try{
               await someAPICall();
           } catch(e) {
              console.log(e)
           }
           count++;
           if(index === items.length-1){
             resolve('Done')
           }
         });
     });
    })();
if(!Array.prototype.forEachAsync) {
    Array.prototype.forEachAsync = function (fn){
      return new Promise((resolve,reject)=>{
        this.forEach(async(item,index,array)=>{
            await fn(item,index,array);
            if(index === array.length-1){
                resolve('done');
            }
        })
      });
    };
  }
require('./Array.prototype.forEachAsync');

let count = 0;

let hello = async (items) => {

// Method 1 - Using the Array.prototype.forEach 

    await items.forEachAsync(async () => {
         try{
               await someAPICall();
           } catch(e) {
              console.log(e)
           }
        count++;
    });

    console.log("count = " + count);
}

someAPICall = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("done") // or reject('error')
        }, 100);
    })
}

hello(['', '', '', '']); // hello([]) empty array is also be handled by default
  await Promise.all(items.map(async (item) => {
        await someAPICall();
        count++;
    }));

    console.log("count = " + count);
// Method 4 - using for loop directly

// 1. Using the modern for(.. in..) loop
   for(item in items){

        await someAPICall();
        count++;
    }

//2. Using the traditional for loop 

    for(let i=0;i<items.length;i++){

        await someAPICall();
        count++;
    }


    console.log("count = " + count);
async function printFiles() {
  const files = await getFilePaths();
  const fileReadPromises = [];

  const readAndLogFile = async filePath => {
    const contents = await fs.readFile(file, "utf8");
    console.log(contents);
    return contents;
  };

  files.forEach(file => {
    fileReadPromises.push(readAndLogFile(file));
  });

  await Promise.all(fileReadPromises);
}

async function printFiles() {
  const files = await getFilePaths();

  for (let i = 0; i < files.length; i++) {
    const file = files[i];
    const contents = await fs.readFile(file, "utf8");
    console.log(contents);
  }
}

export async function asyncForEach<T>(array: Array<T>, callback: (item: T, index: number) => void) {
        for (let index = 0; index < array.length; index++) {
            await callback(array[index], index);
        }
    }
await asyncForEach(receipts, async (eachItem) => {
    await ...
})
const forEach = (arr, cb) => {
  for (let i = 0; i < arr.length; i++) {
    cb(arr[i]);
  }
};
forEach(files, async logFile(file) {
  const contents = await fs.readFile(file, 'utf8');
  console.log(contents);
});
const delay = (ms) => {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
};

const logNumbers = async () => {
  console.log(1);
  await delay(2000);
  console.log(2);
  await delay(2000);
  console.log(3);
};

const main = () => {
  console.log("a");
  logNumbers();
  console.log("b");
};

main();
await asyncForEach(array, async function(item,index,array){
     //await here
   }
)