Как я могу вернуть результат метода fs.lstat из функции - PullRequest
1 голос
/ 08 ноября 2019

Я пытаюсь проверить, является ли данный путь папкой или файлом. Я должен сделать это асинхронно, и отобразить результат в файле мопса, а не на консоли.

const fs = require("fs");
module.exports = function (path) {
fs.lstat(path, (err, stats) => {
    if(err)
        return console.log(err);
    if (stats.isFile())
        return(`Is file: ${stats.isFile()}`);
    if (stats.isDirectory())
        return(`Is directory: ${stats.isDirectory()}`);
}); 

}

1 Ответ

1 голос
/ 08 ноября 2019

3 способа рендеринга обратного вызова в макет мопса

Есть два способа вернуть значение из асинхронной функции, а именно: обратные вызовы или обещания, но, честно говоря, если вы используете вызов только один раз, это не будет всеэто отличается от встраивания вашего вызова в fs.lstat в вашей маршрутизации, поэтому я предоставлю это в качестве третьего варианта.

Структура каталогов для примера

Если вы хотите следовать здесь,структура каталогов для этого примера.

.
├── app.js
├── stat.js
└── views
    └── index.pug

1 directory, 3 files

Установка зависимостей

Вы захотите установить express и pug для этого примера

npm install pug express

Пример макета

Прежде всего, вот пример макета ./views/index.pug, который мы будем использовать в демонстрационных целях:

html
    head
        //- This title comes from the express res.render 
        title= title
    body
        //- This title comes from the express res.render 
        h1= title
        //- This message comes from the express res.render 
        p= statResult

Пример 1: обратные вызовы

Это возможная функция создания отчетов о каталогах / файлах с использованиемобратные вызовы. Обратный вызов - это в основном то, что вы уже отправляете в fs.lstat, где просто вносите простое изменение в его вывод, оборачивая его в наш собственный обратный вызов в стиле узла с именем cb. Обратные вызовы стиля узла обычно имеют два параметра: ошибку в качестве первого параметра и данные в качестве второго. Мы будем следовать шаблону обратного вызова в стиле узла. Обтекание fs.lstat нашим собственным обратным вызовом позволяет функции, вызывающей нашу функцию, получать только те возвращаемые значения, которые мы хотим, а не всю информацию, которую fs.lstat может предоставить в противном случае.

Мы поместили эту функцию в файл с именем stat.js для примера. Если вы не знаете, что делать с ошибкой внутри stat.js, лучше всего передать ошибку через обратный вызов на тот случай, если вызывающая функция сможет лучше обработать ошибку. Важно не глотать / не терять ошибки в Node.

// stat.js
const fs = require("fs");
module.exports = function (path, cb) {
    fs.lstat(path, (err, stats) => {
        if (err)
            return cb(err);
        if (stats.isFile())
            return cb(null, `Is file: ${stats.isFile()}`);
        if (stats.isDirectory())
            return cb(null, `Is directory: ${stats.isDirectory()}`);
    });
}

Использование нашей функции обратного вызова

Вот как простое экспресс-приложение будет использовать этот обратный вызов. Мы поместим это в файл сценария с именем app.js для примера. Обратите внимание, как мы установили для «движка представления» значение «pug», и мы res.render используем «index.pug» в нашем каталоге представлений.

// app.js
const express = require('express');
const app = express();
const stat = require('./stat.js');
const port = 3020;

app.set('view engine', 'pug');

app.get('/views', function (req, res) {
    stat("./views", (err, statResult) => {
        if (err) {
            res.render("Oops something went wrong!");
            console.error(err);
        }
        res.render('index', {
            title: "Views Directory Stat Result",
            statResult: statResult
        })
    })
})

app.get('/', function (req, res) {
    stat("./app.js", (err, statResult) => {
        if (err) {
            res.render("Oops something went wrong!");
            console.error(err);
        }
        res.render('index', {
            title: "App.js Stat Result",
            statResult: statResult
        })
    });
})


app.listen(port, function () {
    console.log("app listening on http://localhost:" + port)
})

Пример 2: обещания

Обещания - действительно удобный инструмент для асинхронного кода, если вы понимаете их достаточно хорошо, они могут принести огромные улучшения в обработке ошибок.

Вот ваш пример кода статистики с использованием обещания. Обратите внимание, как он возвращает вновь созданное обещание, это важно, потому что обещания - это значения, представляющие значение, которое, скорее всего, наступит в будущем. Конструкторы Promises предоставляют вам функцию разрешения и отклонения. Это связано с тем, что обещание может находиться в любом из трех состояний, «ожидающих», что означает, что оно не завершило свое состояние, не «решено» или «отклонено». Отказ от обещания с ошибкой - это все равно что выдать ошибку в синхронном коде. Это замена для нашего старого stat.js файла.

// stat.js
const fs = require("fs");
module.exports = function (path) {
    return new Promise((resolve, reject) => {
        fs.lstat(path, (err, stats) => {
            if (err)
                return reject(err);
            if (stats.isFile())
                return resolve(`Is file: ${stats.isFile()}`);
            if (stats.isDirectory())
                return resolve(`Is directory: ${stats.isDirectory()}`);
        });
    })
}

Ниже описано, как использовать этот файл stat.js в простом приложении. Стоит отметить, что вы должны объединить .then s в обещании получить значение из них, если они разрешены, и если вы хотите поймать любое отклоненное обещание, вам нужно использовать .catch, чтобы поймать их. Как и в случае с кодом синхронизации, когда вы улавливаете ошибку, она предполагает, что вы обработали ошибку, если не сбросили ее. Есть много вещей, которые нужно знать об обещаниях, и я не буду охватывать все ради краткости, но я приведу ссылки на некоторые статьи внизу, где вы можете узнать больше.

Хотя альтернативой цепочке являетсяиспользуйте async / await, где вы используете функцию с ключевым словом async перед ключевым словом функции, которое позволяет вам использовать await значение Promise, как если бы оно было синхронным. Вы можете думать, что await разворачивает ценность обещания. Ниже приведен код для нового app.js в реализации обещания, с маршрутом /views, выполняющим связывание API, и маршрутом /, выполняющим async / await api:

// app.js
const express = require('express');
const app = express();
const stat = require('./stat2.js');
const port = 3020;

app.set('view engine', 'pug');

app.get('/views', function (req, res) {
    stat("./views").then(statResult => {
        res.render('index', {
            title: "Views Directory Stat Result",
            statResult: statResult
        })
    }).catch(function (err) {
        res.render("Oops something went wrong!");
        console.error(err);
    })
})

app.get('/', async function (req, res) {
    try {
        const statResult = await stat("./app.js");
        res.render('index', {
            title: "App.js Stat Result",
            statResult: statResult
        })
    } catch (err) {
        res.render("Oops something went wrong!");
        console.error(err);
    }
})


app.listen(port, function () {
    console.log("app listening on http://localhost:" + port)
})

Пример 3: ВстраиваниеПозвоните в lstat

Это, вероятно, не то, что вы хотите сделать, если вы не хотите повторяться, но всегда есть возможность встроить ваш вызов в lstat. Таким образом, вы бы толькоу меня есть файл app.js, и он будет выглядеть так:

// app.js
const express = require('express');
const app = express();
const fs = require('fs');
const port = 3020;

app.set('view engine', 'pug');

app.get('/views', function (req, res) {
    fs.lstat("./views", (err, stats) => {
        if (err) {
            res.render("Oops something went wrong!");
            console.error(err);
        }
        let statResult = "";
        if (stats.isFile())
            statResult = `Is file: ${stats.isFile()}`;
        if (stats.isDirectory())
            statResult = `Is directory: ${stats.isDirectory()}`;
        res.render('index', {
            title: "Views Directory Stat Result",
            statResult: statResult
        })
    });
})

app.get('/', function (req, res) {
    fs.lstat("./app.js", (err, stats) => {
        if (err) {
            res.render("Oops something went wrong!");
            console.error(err);
        }
        let statResult = "";
        if (stats.isFile())
            statResult = `Is file: ${stats.isFile()}`;
        if (stats.isDirectory())
            statResult = `Is directory: ${stats.isDirectory()}`;
        res.render('index', {
            title: "App.js Stat Result",
            statResult: statResult
        })
    });
})


app.listen(port, function () {
    console.log("app listening on http://localhost:" + port)
})

Ну, это всего лишь три способа вернуть асинхронное значение, которое будет отображаться в pug. Надеюсь, что это поможет, не стесняйтесь задавать мне любые ваши вопросы об этом коде в комментариях. Я искренне предлагаю получить хорошие обещания для вещей, которые при вызове имеют только одно возвращаемое значение.

Вот несколько ссылок на обещания:

Использование обещаний MDN

JavaScript-обещания Джейка Арчибальда: введение

...