Async / प्रतीक्षा के साथ नोड.जेएस में फाइलसिस्टम का उपयोग करना


129

मैं कुछ फाइल सिस्टम ऑपरेशन के साथ async / प्रतीक्षा का उपयोग करना चाहूंगा। आम तौर पर async / वेट ठीक काम करता है क्योंकि मैं उपयोग करता हूं babel-plugin-syntax-async-functions

लेकिन इस कोड के साथ मैं इस मामले में भाग लेता हूं जहां namesअपरिभाषित है:

import fs from 'fs';

async function myF() {
  let names;
  try {
    names = await fs.readdir('path/to/dir');
  } catch (e) {
    console.log('e', e);
  }
  if (names === undefined) {
    console.log('undefined');
  } else {
    console.log('First Name', names[0]);
  }
}

myF();

जब मैं कॉलबैक नरक संस्करण में कोड का पुनर्निर्माण करता हूं तो सब कुछ ठीक है और मुझे फ़ाइल नाम मिलते हैं। आपके संकेत के लिए धन्यवाद।

जवाबों:


139

नोड 8.0.0 के साथ शुरू, आप इसका उपयोग कर सकते हैं:

const fs = require('fs');
const util = require('util');

const readdir = util.promisify(fs.readdir);

async function myF() {
  let names;
  try {
    names = await readdir('path/to/dir');
  } catch (err) {
    console.log(err);
  }
  if (names === undefined) {
    console.log('undefined');
  } else {
    console.log('First Name', names[0]);
  }
}

myF();

Https://nodejs.org/dist/latest-v8.x/docs/api/util.html#util_util_promisify_original देखें


7
नोड v8.9.4 में, एक SyntaxError: Unexpected token importत्रुटि संदेश मिला । क्या नोड 8 importडिफ़ॉल्ट रूप से टोकन का समर्थन करता है ?
मेकरज

9
@makerj वह नए importवाक्यविन्यास का उपयोग कर रहा है । वर्तमान में इसे कुछ ट्रांसप्लीनिंग की आवश्यकता है। यह भी उपयोग करने के लिए ठीक हो जाएगा const fs = require('fs')याconst { promisify } = require('util')
जोश सैंडलिन

2
Noob सवाल, लेकिन {err, names} = functionवाक्य रचना क्या है ?
कासिम

6
@ क्यूसिम इसे विनाशकारी असाइनमेंट कहा जाता है।
जारेडक्राइट

1
@AlexanderZeitler यह सच हो सकता है। मैंने यह देखने के लिए नहीं देखा कि क्या वास्तव में विनाश का सही उपयोग है। Async प्रतीक्षा के मामले में मुझे लगता है कि आप बस करेंगे names = await readdir('path/to/dir');और यदि ब्लॉक errमें इसे संभालना है catch। किसी भी तरह से, सिंटैक्स का नाम विनाशकारी कार्य है जो कासिम के प्रश्न के जवाब में था।

88

Nync 11 के बाद से async प्रतीक्षित fs फ़ंक्शन के लिए मूल समर्थन

चूंकि Node.JS 11.0.0 (स्थिर), और संस्करण 10.0.0 (प्रायोगिक), आपके पास फ़ाइल सिस्टम विधियों तक पहुंच है, जो पहले से ही प्रांतीय हैं और आप उनका उपयोग कर सकते हैं try catch कॉलबैक के दिए गए मान को शामिल करने के बजाय जाँच के अलावा अपवाद हैंडलिंग के हैं। एक त्रुटि।

एपीआई बहुत साफ और सुंदर है! बस वस्तु के .promisesसदस्य का उपयोग करें fs:

import fs from 'fs';
const fsPromises = fs.promises;

async function listDir() {
  try {
    return fsPromises.readdir('path/to/dir');
  } catch (err) {
    console.error('Error occured while reading directory!', err);
  }
}

listDir();

यह API Node.js साइट पर फ़ाइल सिस्टम डॉक्यूमेंटेशन के संस्करण 11.x के अनुसार स्थिर है
TheHanna

1
@DanStarns यदि आप return awaitअपना वादा नहीं निभाते हैं , तो कैच ब्लॉक का कोई फायदा नहीं है ... मैं पतंजलि को कभी-कभी लौटने से पहले इंतजार करना अच्छा अभ्यास है
538ROMEO

@ 538ROMEO ने सिर्फ इस पर और आपके अधिकार में देखा। इस पर ध्यान दिलाने के लिए धन्यवाद।
DanStarns

इन वैकल्पिक तरीकों के लिए दस्तावेज़ीकरण: nodejs.org/api/fs.html#fs_fs_promises_api
जीवन

87

नोड .js 8.0.0

मूल निवासी async / प्रतीक्षा करें

Promisify

इस संस्करण से, आप से देशी Node.js समारोह का उपयोग कर सकते util पुस्तकालय।

const fs = require('fs')
const { promisify } = require('util')

const readFileAsync = promisify(fs.readFile)
const writeFileAsync = promisify(fs.writeFile)

const run = async () => {
  const res = await readFileAsync('./data.json')
  console.log(res)
}

run()

रैपिंग का वादा

const fs = require('fs')

const readFile = (path, opts = 'utf8') =>
  new Promise((resolve, reject) => {
    fs.readFile(path, opts, (err, data) => {
      if (err) reject(err)
      else resolve(data)
    })
  })

const writeFile = (path, data, opts = 'utf8') =>
  new Promise((resolve, reject) => {
    fs.writeFile(path, data, opts, (err) => {
      if (err) reject(err)
      else resolve()
    })
  })

module.exports = {
  readFile,
  writeFile
}

...


// in some file, with imported functions above
// in async block
const run = async () => {
  const res = await readFile('./data.json')
  console.log(res)
}

run()

सलाह

हमेशा try..catchप्रतीक्षा ब्लॉकों के लिए उपयोग करें , यदि आप ऊपरी अपवाद को वापस नहीं करना चाहते हैं।


यह अजीब है। मुझे SyntaxError मिल रही है: इंतजार केवल async फ़ंक्शन में मान्य है ... रोष में रो रहा है।
वेदरन मारिसेविक।

2
@VedranMaricevic। टिप्पणियों को देखें, awaitहमेशा asyncब्लॉक में होना चाहिए :)
डिंपीयाक्स

@VedranMaricevic। आपको कॉल करने की आवश्यकता है कि const res = await readFile('data.json') console.log(res)कुछ async फ़ंक्शन में
Jayraj

वादा रैपिंग fs.promisesऔर इसके साथ उपयोग async/awaitकरना मेरे लिए बहुत उलझन की बात है
Oldboy

@PrimitiveNom Promise का उपयोग पारंपरिक तरीके से किया जा सकता है then, catchआदि जहां async / प्रतीक्षा है, आधुनिक व्यवहार प्रवाह है।
डिंपियाक्स

43

आप गलत व्यवहार उत्पन्न कर सकते हैं क्योंकि फ़ाइल-एप fs.readdirएक वादा वापस नहीं करता है। यह केवल एक कॉलबैक लेता है। यदि आप async-wait सिंटैक्स के साथ जाना चाहते हैं तो आप इस तरह से फंक्शन को 'प्रॉमिस' कर सकते हैं:

function readdirAsync(path) {
  return new Promise(function (resolve, reject) {
    fs.readdir(path, function (error, result) {
      if (error) {
        reject(error);
      } else {
        resolve(result);
      }
    });
  });
}

और इसके बजाय इसे कॉल करें:

names = await readdirAsync('path/to/dir');

31

V10.0 के रूप में , आप उपयोग कर सकते हैंfs.Promises

उदाहरण का उपयोग कर readdir

const { promises: fs } = require("fs");

async function myF() {
    let names;
    try {
        names = await fs.readdir("path/to/dir");
    } catch (e) {
        console.log("e", e);
    }
    if (names === undefined) {
        console.log("undefined");
    } else {
        console.log("First Name", names[0]);
    }
}

myF();

उदाहरण का उपयोग कर readFile

const { promises: fs } = require("fs");

async function getContent(filePath, encoding = "utf-8") {
    if (!filePath) {
        throw new Error("filePath required");
    }

    return fs.readFile(filePath, { encoding });
}

(async () => {
    const content = await getContent("./package.json");

    console.log(content);
})();

महान काम करता है, लेकिन ExperimentalWarning: The fs.promises API is experimentalचेतावनी के बारे में खुला मुद्दा नोट करने के लिए महत्वपूर्ण है : github.com/pnpm/pnpm/issues/1178
DavidP

1
@DavidP नोड के किस संस्करण का उपयोग कर रहे हैं? 12 और ऊपर ठीक काम करता है
DanStarns

2
हाँ! बिल्कुल सही - मैं राज्य के संस्करण की उपेक्षा कर रहा हूं जिस पर मैं हूं: v10.15.3- यह संदेश को दबाने के लिए संभव है। हालाँकि, इस मुद्दे के साथ अभी भी खुला है कि मैंने इसे ध्यान देने योग्य समझा।
डेविड

1
@ डेविड मैं इसका मतलब है कि यह एक उल्लेख के लायक है मुझे गलत मत समझो, लेकिन नोड 12 अब एलटीएस में है इसलिए यह एक बिग्गी नहीं है।
DanStarns

कैसे वास्तव में आप के साथ इस का उपयोग करते हैं, का कहना है readFile? im इस पूरे वादे की बात के लिए नया है, और सब मैं करना चाहता है एक समारोह है getContentकि मैं अपनी स्क्रिप्ट में विभिन्न भागों में कॉल और प्रतीक्षा कर सकता हूं, फिर भी यह बहुत भ्रामक साबित हो रहा है
Oldboy

8

यह प्रश्न के लिए टाइपस्क्रिप्ट संस्करण है। यह नोड 11.0 के बाद प्रयोग करने योग्य है:

import { promises as fs } from 'fs';

async function loadMonoCounter() {
    const data = await fs.readFile('monolitic.txt', 'binary');
    return Buffer.from(data);
}

5

यहाँ मेरे लिए क्या काम किया गया है:

const fsp = require('fs-promise');

(async () => {
  try {
    const names = await fsp.readdir('path/to/dir');
    console.log(names[0]);
  } catch (e) {
    console.log('error: ', e);
  }
})();

यह कोड बबल के बिना नोड 7.6 में काम करता है जब सद्भाव ध्वज सक्षम होता है node --harmony my-script.js:। और नोड 7.7 के साथ शुरू, आपको इस ध्वज की आवश्यकता नहीं है !

fspशुरुआत में शामिल की गई लाइब्रेरी fs(और fs-ext) के लिए केवल एक उचित आवरण है ।

मैं वास्तव में इस बात से बाहर हूँ कि आप इन दिनों बाबेल के बिना नोड में क्या कर सकते हैं! नेटिव async/ awaitराइटिंग कोड को ऐसे बनाएं आनंद!

अद्यतन 2017-06: एफएस-वादा मॉड्यूल को हटा दिया गया था। fs-extraइसके बजाय एक ही एपीआई के साथ प्रयोग करें ।


इसके लिए एक पुस्तकालय डाउनलोड करना शुद्ध ओवरकिल है, निर्भरता फूला हुआ है जो कि समुदाय के खिलाफ दृढ़ता से होना चाहिए, एक नए npmjs को निष्क्रिय करना चाहिए जो केवल 0 निर्भरता के साथ काम करता है
PirateApp

5

कस्टम कार्यों की तुलना में एक npm पैकेज जैसे https://github.com/davetemplin/async-file का उपयोग करने की सलाह देते हैं । उदाहरण के लिए:

import * as fs from 'async-file';

await fs.rename('/tmp/hello', '/tmp/world');
await fs.appendFile('message.txt', 'data to append');
await fs.access('/etc/passd', fs.constants.R_OK | fs.constants.W_OK);

var stats = await fs.stat('/tmp/hello', '/tmp/world');

अन्य उत्तर पुराने हैं


5

मेरे पास यह थोड़ा मदद करने वाला मॉड्यूल है जो कार्यों के प्रोमिसिफाइड संस्करणों को निर्यात fsकरता है

const fs = require("fs");
const {promisify} = require("util")

module.exports = {
  readdir: promisify(fs.readdir),
  readFile: promisify(fs.readFile),
  writeFile: promisify(fs.writeFile)
  // etc...
};

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.