Async का उपयोग करना / forEach लूप के साथ प्रतीक्षा करना

Jun 02 2016

वहाँ का उपयोग कर के साथ किसी भी मुद्दे हैं async/ awaitएक में forEachपाश? मैं फ़ाइलों की एक सरणी के माध्यम से और awaitप्रत्येक फ़ाइल की सामग्री पर लूप करने की कोशिश कर रहा हूं ।

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/ उपयोग करने वाले नहीं हैं await, इसलिए मैं सिर्फ यह पूछना चाहता था कि क्या इसके लिए कोई समस्या थी।

जवाब

2680 Bergi Jun 02 2016 at 02:02

यकीन है कि कोड काम करता है, लेकिन मुझे पूरा यकीन है कि यह वह नहीं करता है जो आप इसे करने की उम्मीद करते हैं। यह सिर्फ कई अतुल्यकालिक कॉल बंद कर देता है, लेकिन इसके printFilesतुरंत बाद फ़ंक्शन वापस आ जाता है।

क्रम से पढ़ना

यदि आप फ़ाइलों को अनुक्रम में पढ़ना चाहते हैं, तो आपforEach वास्तव में उपयोग नहीं कर सकतेfor … ofइसके बजाय बस एक आधुनिक लूप का उपयोग करें, जिसमें awaitउम्मीद के मुताबिक काम होगा:

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.all:

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

  await Promise.all(files.map(async (file) => {
    const contents = await fs.readFile(file, 'utf8')
    console.log(contents)
  }));
}
274 FranciscoMateo Jun 15 2018 at 18:17

ES2018 के साथ, आप उपरोक्त सभी उत्तरों को सरल बनाने में सक्षम हैं:

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

  for await (const contents of fs.readFile(file, 'utf8')) {
    console.log(contents)
  }
}

कल्पना देखें: प्रस्ताव-एसिंक्स-पुनरावृत्ति


2018-09-10: इस उत्तर पर हाल ही में बहुत ध्यान दिया जा रहा है, कृपया अतुल्यकालिक पुनरावृत्ति के बारे में अधिक जानकारी के लिए एक्सल रौशमेयर के ब्लॉग पोस्ट को देखें: ES2018: अतुल्यकालिक पुनरावृत्ति

81 TimothyZorn Mar 27 2018 at 02:48

Promise.allके साथ संयोजन के बजाय Array.prototype.map(जो उस क्रम की गारंटी नहीं देता है जिसमें Promiseएस को हल किया जाता है), मैं उपयोग करता हूं Array.prototype.reduce, एक हल के साथ शुरू होता है Promise:

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

  await files.reduce(async (promise, file) => {
    // This line will wait for the last async function to finish.
    // The first iteration uses an already resolved Promise
    // so, it will immediately continue.
    await promise;
    const contents = await fs.readFile(file, 'utf8');
    console.log(contents);
  }, Promise.resolve());
}
35 AntonioVal Jul 10 2017 at 15:15

पी-यात्रा NPM लागू सरणी यात्रा तरीकों ताकि वे async / इंतजार के साथ एक बहुत सरल तरीके से इस्तेमाल किया जा सकता पर मॉड्यूल।

आपके मामले के साथ एक उदाहरण:

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);
  });
})();
32 Matt Mar 22 2018 at 22:11

यहाँ कुछ forEachAsyncप्रोटोटाइप हैं। नोट आपको awaitउनकी आवश्यकता होगी :

Array.prototype.forEachAsync = async function (fn) {
    for (let t of this) { await fn(t) }
}

Array.prototype.forEachAsyncParallel = async function (fn) {
    await Promise.all(this.map(fn));
}

ध्यान दें कि आप इसे अपने कोड में शामिल कर सकते हैं, आपको इसे उन पुस्तकालयों में शामिल नहीं करना चाहिए जिन्हें आप दूसरों को वितरित करते हैं (अपने ग्लोबल्स को प्रदूषित करने से बचने के लिए)।

9 chharvey Feb 23 2018 at 07:47

@ बर्गी के जवाब के अलावा , मैं एक तीसरा विकल्प देना चाहूंगा। यह @ बर्गी के 2 के उदाहरण से बहुत मिलता-जुलता है, लेकिन प्रत्येक readFileव्यक्ति की प्रतीक्षा करने के बजाय , आप वादों की एक सरणी बनाते हैं, जिनमें से प्रत्येक का आप अंत में इंतजार करते हैं।

import fs from 'fs-promise';
async function printFiles () {
  const files = await getFilePaths();

  const promises = files.map((file) => fs.readFile(file, 'utf8'))

  const contents = await Promise.all(promises)

  contents.forEach(console.log);
}

ध्यान दें कि फ़ंक्शन को पारित करने की .map()आवश्यकता नहीं है async, क्योंकि fs.readFileवैसे भी एक वादा वस्तु देता है। इसलिए promisesवादा वस्तुओं की एक सरणी है, जिसे भेजा जा सकता है Promise.all()

@ बर्गी के उत्तर में, कंसोल फ़ाइल सामग्री को उस क्रम में लॉग कर सकता है जिस क्रम में वे पढ़ रहे हैं। उदाहरण के लिए यदि वास्तव में एक छोटी फ़ाइल वास्तव में बड़ी फ़ाइल से पहले पढ़ना समाप्त कर देती है, तो उसे पहले लॉग किया जाएगा, भले ही सरणी में बड़ी फ़ाइल के बाद छोटी फ़ाइल आती होfiles । हालाँकि, ऊपर मेरी विधि में, आपको गारंटी है कि कंसोल उसी क्रम में फ़ाइलों को लॉग करेगा जो प्रदान की गई सरणी में है।

7 master_dodo May 27 2019 at 05:08

जब fsवादा किया जाता है तब बर्गी का समाधान अच्छी तरह से काम करता है। आप उपयोग कर सकते हैं bluebird, fs-extraया इसके fs-promiseलिए।

हालाँकि, नोड के मूल fsपरिवाद के लिए समाधान इस प्रकार है:

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;
    }));

नोट: require('fs') अनिवार्य रूप से 3 तर्क के रूप में कार्य करता है, अन्यथा त्रुटि फेंकता है:

TypeError [ERR_INVALID_CALLBACK]: Callback must be a function
6 HoomanAskari Aug 26 2017 at 17:47

काम के ऊपर दोनों समाधान, हालांकि, एंटोनियो कम कोड के साथ काम करता है, यहां बताया गया है कि इसने मुझे अपने डेटाबेस से डेटा को हल करने में मदद की, कई अलग-अलग बच्चों के रिफ से और फिर उन सभी को एक सरणी में धकेल दिया और सभी के बाद एक वादा में इसे हल किया किया हुआ:

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)))
5 JayEdwards Sep 23 2017 at 06:03

यह एक फ़ाइल में कुछ तरीकों को पॉप करने के लिए बहुत दर्दनाक है जो क्रमबद्ध क्रम में अतुल्यकालिक डेटा को संभालेंगे और अपने कोड को अधिक पारंपरिक स्वाद देंगे। उदाहरण के लिए:

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));
}
5 OliverDixon Apr 17 2020 at 00:18

यह समाधान मेमोरी-ऑप्टिमाइज़्ड भी है ताकि आप इसे 10,000 डेटा आइटम और अनुरोधों पर चला सकें। यहां कुछ अन्य समाधान बड़े डेटा सेट पर सर्वर को क्रैश कर देंगे।

टाइपस्क्रिप्ट में:

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 ...
})
4 LeOn-HanLi Sep 25 2017 at 03:00

एक महत्वपूर्ण चेतावनी है: await + for .. ofतरीका और forEach + asyncतरीका वास्तव में अलग-अलग प्रभाव डालता है।

awaitएक असली forलूप के अंदर होने से यह सुनिश्चित हो जाएगा कि सभी async कॉल को एक-एक करके निष्पादित किया जाता है। और जिस forEach + asyncतरह से एक ही समय में सभी वादों को आग लगाएगा, जो तेज है लेकिन कभी-कभी अभिभूत हो जाता है ( यदि आप कुछ डीबी क्वेरी करते हैं या वॉल्यूम प्रतिबंधों के साथ कुछ वेब सेवाओं पर जाते हैं और एक बार में 100,000 कॉल फायर नहीं करना चाहते हैं)।

आप उपयोग नहीं कर सकते reduce + promise(कम सुरुचिपूर्ण) यदि आप उपयोग नहीं करते हैं async/awaitऔर सुनिश्चित करना चाहते हैं कि फाइलें एक के बाद एक पढ़ी जाएं ।

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);
    }
}
4 gsaandy Dec 01 2019 at 23:59

सिर्फ मूल उत्तर से जोड़कर

  • मूल उत्तर में समानांतर रीडिंग सिंटैक्स कभी-कभी भ्रमित और पढ़ने में मुश्किल होता है, शायद हम इसे एक अलग दृष्टिकोण में लिख सकते हैं
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);
  }
}

4 lukaswilkeer Dec 21 2019 at 08:11

@ बर्गी की प्रतिक्रिया की तरह, लेकिन एक अंतर के साथ।

Promise.all यदि कोई अस्वीकृत हो जाता है तो सभी वादों को खारिज कर देता है।

तो, एक पुनरावर्तन का उपयोग करें।

const readFilesQueue = async (files, index = 0) {
    const contents = await fs.readFile(files[index], 'utf8')
    console.log(contents)

    return files.length <= index
        ? readFilesQueue(files, ++index)
        : files

}

const printFiles async = () => {
    const files = await getFilePaths();
    const printContents = await readFilesQueue(files)

    return printContents
}

printFiles()

पुनश्च

readFilesQueueprintFilesसाइड इफेक्ट के कारण से बाहर है * द्वारा शुरू की console.log, यह नकली, परीक्षण, या जासूसी करने के लिए बेहतर है इसलिए, यह एक ऐसा फ़ंक्शन है जो सामग्री (सिडेनोट) लौटाता है ठंडा नहीं है।

इसलिए, कोड को बस उसी द्वारा डिज़ाइन किया जा सकता है: तीन अलग-अलग फ़ंक्शन जो "शुद्ध" ** हैं और कोई साइड इफेक्ट्स नहीं देते हैं, पूरी सूची की प्रक्रिया करते हैं और विफल मामलों को संभालने के लिए आसानी से संशोधित किया जा सकता है।

const files = await getFilesPath()

const printFile = async (file) => {
    const content = await fs.readFile(file, 'utf8')
    console.log(content)
}

const readFiles = async = (files, index = 0) => {
    await printFile(files[index])

    return files.lengh <= index
        ? readFiles(files, ++index)
        : files
}

readFiles(files)

भविष्य संपादित करें / वर्तमान स्थिति

नोड शीर्ष-स्तर की प्रतीक्षा का समर्थन करता है (इसमें अभी तक प्लगइन नहीं है, सामंजस्यपूर्ण झंडे के माध्यम से सक्षम नहीं किया जा सकता है), यह शांत है, लेकिन एक समस्या को हल नहीं करता है (रणनीतिक रूप से मैं केवल एलटीएस संस्करणों पर काम करता हूं)। फाइलें कैसे प्राप्त करें?

रचना का उपयोग करना। कोड को देखते हुए, मुझे सनसनी का कारण बनता है कि यह एक मॉड्यूल के अंदर है, इसलिए, इसे करने के लिए एक फ़ंक्शन होना चाहिए। यदि नहीं, तो आपको एक आईआईएफई का उपयोग करना चाहिए ताकि एक समान फ़ंक्शन में भूमिका कोड को लपेटकर सरल मॉड्यूल का निर्माण किया जा सके जो आपके लिए सब कुछ है, या आप सही तरीके से जा सकते हैं, रचना है।

// more complex version with IIFE to a single module
(async (files) => readFiles(await files())(getFilesPath)

ध्यान दें कि शब्दार्थ के कारण परिवर्तनशील का नाम बदल जाता है। आप एक फ़ंक्टर (एक फ़ंक्शन जिसे किसी अन्य फ़ंक्शन द्वारा आमंत्रित किया जा सकता है) पास करते हैं और मेमोरी पर एक पॉइंटर को पुनः प्राप्त करते हैं जिसमें एप्लिकेशन के तर्क का प्रारंभिक ब्लॉक होता है।

लेकिन, अगर एक मॉड्यूल नहीं है और आपको तर्क निर्यात करने की आवश्यकता है?

फ़ंक्शन को एक async फ़ंक्शन में लपेटें।

export const readFilesQueue = async () => {
    // ... to code goes here
}

या चर के नाम बदलो, जो भी ...


* साइड इफ़ेक्ट मेनन द्वारा एप्लिकेशन के किसी भी कोलेटेरल प्रभाव को प्रभावित करता है जो आईओ की तरह, एप्लिकेशन में स्टेट / व्यवहार या इनग्रॉस बग को बदल सकता है।

** "शुद्ध" द्वारा, यह एपोस्ट्रोफ़ में है क्योंकि फ़ंक्शन यह शुद्ध नहीं है और कोड को शुद्ध संस्करण में परिवर्तित किया जा सकता है, जब कोई कंसोल आउटपुट नहीं होता है, केवल डेटा जोड़तोड़ होता है।

इसके अलावा, शुद्ध होने के लिए, आपको साइड इफेक्ट्स को संभालने वाले मोनाड्स के साथ काम करने की आवश्यकता होगी, जो त्रुटि प्रवण हैं, और उस त्रुटि को अनुप्रयोग के अलग-अलग मानते हैं।

3 Babakness Feb 28 2018 at 11:41

टास्क, फ्यूचरिज़ और ट्रैवर्सेबल लिस्ट का उपयोग करके, आप बस कर सकते हैं

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

  List(files).traverse( Task.of, f => readFile( f, 'utf-8'))
    .fork( console.error, console.log)
}

यहाँ बताया गया है कि आप इसे कैसे सेट करेंगे

import fs from 'fs';
import { futurize } from 'futurize';
import Task from 'data.task';
import { List } from 'immutable-ext';

const future = futurizeP(Task)
const readFile = future(fs.readFile)

एक और तरीका है वांछित कोड संरचित होगा

const printFiles = files => 
  List(files).traverse( Task.of, fn => readFile( fn, 'utf-8'))
    .fork( console.error, console.log)

या शायद और भी अधिक कार्यात्मक रूप से उन्मुख

// 90% of encodings are utf-8, making that use case super easy is prudent

// handy-library.js
export const readFile = f =>
  future(fs.readFile)( f, 'utf-8' )

export const arrayToTaskList = list => taskFn => 
  List(files).traverse( Task.of, taskFn ) 

export const readFiles = files =>
  arrayToTaskList( files, readFile )

export const printFiles = files => 
  readFiles(files).fork( console.error, console.log)

फिर मूल कार्य से

async function main() {
  /* awesome code with side-effects before */
  printFiles( await getFiles() );
  /* awesome code with side-effects after */
}

यदि आप वास्तव में एन्कोडिंग में अधिक लचीलापन चाहते हैं, तो आप ऐसा कर सकते हैं (मज़े के लिए, मैं प्रस्तावित पाइप फॉरवर्ड ऑपरेटर का उपयोग कर रहा हूं )

import { curry, flip } from 'ramda'

export const readFile = fs.readFile 
  |> future,
  |> curry,
  |> flip

export const readFileUtf8 = readFile('utf-8')

PS - मैंने कंसोल पर इस कोड की कोशिश नहीं की, हो सकता है कि कुछ टाइपो हो ... "सीधे फ्रीस्टाइल, गुंबद के ऊपर से!" जैसा कि 90 के दशक के बच्चे कहेंगे। :-P

3 Beau Mar 13 2019 at 06:31

वर्तमान में Array.forEach प्रोटोटाइप प्रॉपर्टी, एसिंक्स ऑपरेशंस का समर्थन नहीं करती है, लेकिन हम अपनी जरूरतों को पूरा करने के लिए अपना पॉली-फिल बना सकते हैं।

// 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}

और बस! अब आपके पास किसी भी सरणियों पर एक async फोरैच विधि उपलब्ध है जो इन ऑपरेशनों के बाद परिभाषित होती है।

आइए इसका परीक्षण करते हैं ...

// 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

... और इसी तरह :)

ध्यान देने योग्य कुछ बातें:

  • आपका इटेरिफ़ंक्शन एक एसिंक्स फ़ंक्शन या वादा होना चाहिए
  • इससे पहले बनाए गए किसी भी सरण Array.prototype.<yourAsyncFunc> = <yourAsyncFunc>में यह सुविधा उपलब्ध नहीं होगी
3 PranavKAndro Nov 25 2019 at 03:31

आज मैं इसके लिए कई समाधानों पर आया हूं। एस्कॉन वेट चलाने के लिए लूप में काम करता है। चारों ओर आवरण बनाकर हम ऐसा कर सकते हैं।

देशी के लिए यह आंतरिक रूप से कैसे काम करता है, इस पर अधिक विस्तृत विवरण और क्यों यह एक async फ़ंक्शन कॉल करने में सक्षम नहीं है और विभिन्न तरीकों पर अन्य विवरण यहां लिंक में दिए गए हैं

कई तरीके जिनके माध्यम से यह किया जा सकता है और वे निम्नानुसार हैं,

विधि 1: आवरण का उपयोग करना।

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')
           }
         });
     });
    })();

विधि 2: Array.prototype के जेनेरिक फ़ंक्शन के समान उपयोग करना

Array.prototype.forEachAsync.js

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

विधि 3:

Promise.all का उपयोग करना

  await Promise.all(items.map(async (item) => {
        await someAPICall();
        count++;
    }));

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

विधि 4: लूप के लिए पारंपरिक या लूप के लिए आधुनिक

// 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);
3 richytong May 21 2020 at 03:57

आप उपयोग कर सकते हैं Array.prototype.forEach, लेकिन async / प्रतीक्षा इतनी संगत नहीं है। ऐसा इसलिए है क्योंकि एक async कॉलबैक से दिया गया वादा हल होने की उम्मीद Array.prototype.forEachकरता है , लेकिन इसके कॉलबैक के निष्पादन से किसी भी वादे को हल नहीं करता है। तो, आप forEach का उपयोग कर सकते हैं, लेकिन आपको खुद ही वादा समाधान संभालना होगा।

यहां श्रृंखला का उपयोग करके प्रत्येक फ़ाइल को पढ़ने और प्रिंट करने का एक तरीका है Array.prototype.forEach

async function printFilesInSeries () {
  const files = await getFilePaths()

  let promiseChain = Promise.resolve()
  files.forEach((file) => {
    promiseChain = promiseChain.then(() => {
      fs.readFile(file, 'utf8').then((contents) => {
        console.log(contents)
      })
    })
  })
  await promiseChain
}

Array.prototype.forEachसमानांतर में फ़ाइलों की सामग्री को प्रिंट करने का एक तरीका (अभी भी उपयोग कर रहा है ) है

async function printFilesInParallel () {
  const files = await getFilePaths()

  const promises = []
  files.forEach((file) => {
    promises.push(
      fs.readFile(file, 'utf8').then((contents) => {
        console.log(contents)
      })
    )
  })
  await Promise.all(promises)
}
2 jgmjgm Oct 15 2019 at 01:35

यह देखने के लिए कि यह कैसे गलत हो सकता है, विधि के अंत में कंसोल.लॉग प्रिंट करें।

चीजें जो सामान्य रूप से गलत हो सकती हैं:

  • मनमाना आदेश।
  • PrintFiles फाइलों को प्रिंट करने से पहले पूरा कर सकते हैं।
  • घटिया प्रदर्शन।

ये हमेशा गलत नहीं होते हैं लेकिन अक्सर मानक उपयोग के मामलों में होते हैं।

आम तौर पर, forEach का उपयोग करने के परिणामस्वरूप सभी अंतिम होंगे। यह फ़ंक्शन के लिए प्रतीक्षा किए बिना प्रत्येक फ़ंक्शन को कॉल करेगा जिसका अर्थ है कि यह सभी फ़ंक्शन को शुरू करने के लिए कहता है फिर फ़ंक्शंस के समाप्त होने के लिए इंतजार किए बिना समाप्त होता है।

import fs from 'fs-promise'

async function printFiles () {
  const files = (await getFilePaths()).map(file => fs.readFile(file, 'utf8'))

  for(const file of files)
    console.log(await file)
}

printFiles()

यह मूल जेएस में एक उदाहरण है जो आदेश को संरक्षित करेगा, फ़ंक्शन को समय से पहले लौटने से रोकेगा और सिद्धांत में इष्टतम प्रदर्शन को बनाए रखेगा।

यह करेगा:

  • फ़ाइल के सभी समानांतर में होने के लिए पढ़ता है।
  • प्रतीक्षा करने के वादे के लिए फ़ाइल नाम को मैप करने के लिए मानचित्र के उपयोग के माध्यम से ऑर्डर को संरक्षित करें।
  • सरणी द्वारा परिभाषित क्रम में प्रत्येक वादे की प्रतीक्षा करें।

इस समाधान के साथ पहली फाइल दिखाई जाएगी जैसे ही यह उपलब्ध होगी बिना दूसरों की प्रतीक्षा किए पहले उपलब्ध होने की।

यह एक ही समय में सभी फाइलों को लोड करने के बजाय दूसरी फाइल पढ़ने से पहले पहले खत्म होने का इंतजार करने के लिए होगा।

इसका केवल एक ही मूल संस्करण है और मूल संस्करण यह है कि यदि एक ही बार में कई रीडियाँ शुरू की जाती हैं, तो एक बार में अधिक त्रुटियां होने के कारण त्रुटियों को संभालना अधिक कठिन होता है।

ऐसे संस्करणों के साथ, जो एक समय में एक फ़ाइल पढ़ते हैं, फिर किसी भी अधिक फ़ाइलों को पढ़ने का प्रयास किए बिना समय बर्बाद किए बिना असफल हो जाएंगे। यहां तक ​​कि एक विस्तृत रद्दीकरण प्रणाली के साथ यह पहली फ़ाइल पर विफल होने से बचने के लिए कठिन हो सकता है, लेकिन पहले से ही अन्य फ़ाइलों के अधिकांश को पढ़ना।

प्रदर्शन हमेशा अनुमानित नहीं होता है। जबकि कई सिस्टम समानांतर फाइल रीडिंग के साथ तेज़ होंगे, कुछ अनुक्रमिक पसंद करेंगे। कुछ गतिशील हैं और लोड के तहत बदलाव कर सकते हैं, अनुकूलन जो विलंबता प्रदान करते हैं वे हमेशा भारी विवाद के तहत अच्छे थ्रूपुट का उत्पादन नहीं करते हैं।

उस उदाहरण में कोई त्रुटि हैंडलिंग भी नहीं है। अगर कुछ की आवश्यकता होती है, तो उन्हें या तो सभी को सफलतापूर्वक दिखाया जाना चाहिए या बिल्कुल नहीं।

प्रत्येक चरण में कंसोल.लॉग के साथ गहराई से प्रयोग करने की सिफारिश की जाती है और नकली फ़ाइल रीड सॉल्यूशंस (इसके बजाय यादृच्छिक देरी)। हालांकि कई समाधान सरल मामलों में भी ऐसा ही करते हैं, सभी में सूक्ष्म अंतर होते हैं जो निचोड़ने के लिए कुछ अतिरिक्त जांच करते हैं।

समाधानों के बीच अंतर बताने में मदद करने के लिए इस मॉक का उपयोग करें:

(async () => {
  const start = +new Date();
  const mock = () => {
    return {
      fs: {readFile: file => new Promise((resolve, reject) => {
        // Instead of this just make three files and try each timing arrangement.
        // IE, all same, [100, 200, 300], [300, 200, 100], [100, 300, 200], etc.
        const time = Math.round(100 + Math.random() * 4900);
        console.log(`Read of ${file} started at ${new Date() - start} and will take ${time}ms.`)
        setTimeout(() => {
          // Bonus material here if random reject instead.
          console.log(`Read of ${file} finished, resolving promise at ${new Date() - start}.`);
          resolve(file);
        }, time);
      })},
      console: {log: file => console.log(`Console Log of ${file} finished at ${new Date() - start}.`)},
      getFilePaths: () => ['A', 'B', 'C', 'D', 'E']
    };
  };

  const printFiles = (({fs, console, getFilePaths}) => {
    return async function() {
      const files = (await getFilePaths()).map(file => fs.readFile(file, 'utf8'));

      for(const file of files)
        console.log(await file);
    };
  })(mock());

  console.log(`Running at ${new Date() - start}`);
  await printFiles();
  console.log(`Finished running at ${new Date() - start}`);
})();

ScottRudiger Jun 21 2018 at 23:55

एंटोनियो वाल्स के समान p-iteration, एक वैकल्पिक एनपीएम मॉड्यूल है async-af:

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();

वैकल्पिक रूप से, async-afएक स्थिर विधि (log / logAF) है जो वादों के परिणामों को लॉग करती है:

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();

async-af