I can await fs.readdir but I don't know why - javascript

https://github.com/SimulatedGREG/electron-vue
I used this template to make electron.
And I am using this library.
https://www.npmjs.com/package/fs-extra
https://nodejs.org/docs/latest-v11.x/api/fs.html
By this document, I can write like this.
await fs.readdir
But the electron template, it is using electron#2.0.4 and which is using node#8.9.3.
So I checked here.
https://nodejs.org/docs/latest-v8.x/api/fs.html
It looks like the function doesn't return promise.
But I actually can await fs functions using fs-extra in electron#2.0.4.
Both develop and build.
Why is this?
result of
console.log(fs.readdir())
Is like below.
It's Promise.
But I don't know why I can do this in electron#2.0.4.

You can use fs module in node v8. the return value will be passed to callback function
const fs = require('fs');
fs.readdir(dir, function(err, list) {
// do your logic with list array
})

If you're using Node > 8.16 (I believe), you can use promisify in the utils module:
const { promisify } = require('utils');
const fs = require('fs');
const readdir = promisify(fs.readdir);
(async () => {
const res = await readdir('./path');
console.log(res);
})();

Sorry, I am not good at English.
And, I am a beginner web developer.
This is just an anticipation.
I saw package.json of "fs-extra".
And I could not find "fs" inside that.
It is using a library called "graceful-fs", but this library does not require "fs" neither.
Maybe, "fs-extra" is not relevant to "fs".
And it has own logic that is already promisified even in node lower than verstion10.
Any one know the truth?

Related

TypeError: fs.createWriteStream is not a function in Node

I couldn't find any resources online explaining why I'm running into this issue, even the official Node JS docs / API reference say that createWriteStream is a method in fs:
fs.createWriteStream(path[, options])[src]#
All other stack overflow questions I found were people who were accidentally trying to access fs from the browser. So just to clarify, I am using Node!!
Example Code:
import fs from 'fs/promises'
let ws = fs.createWriteStream("example.png")
Example code output:
file:///workspace/buz/src/error.js:3
let ws = fs.createWriteStream("example.png")
^
TypeError: fs.createWriteStream is not a function
at file:///workspace/buz/src/error.js:3:13
at ModuleJob.run (node:internal/modules/esm/module_job:198:25)
at async Promise.all (index 0)
at async ESMLoader.import (node:internal/modules/esm/loader:385:24)
at async loadESM (node:internal/process/esm_loader:88:5)
at async handleMainPromise (node:internal/modules/run_main:61:12)
Misc:
Node version: v16.15.1
OS: Mac OS
I figured it out:
createWriteStream() is a function of fs, but not of fs/promises!!
I couldn't find ANY documentation online for how to use createWriteStream() with fs promises, so the easiest option is just to import it from the normal callback based fs:
import fs from 'fs/promises'
import {createWriteStream} from 'fs'
let ws = fs.createWriteStream("example.png")
I read through the Node documentation on fs and went through all the methods in the the fs/promises API and none of them return a <WriteStream>. So as of today, it seems like there's no way to get around this issue without importing stuff from the normal fs API.
Update: Changed wording to not use the word synchronous when describing the callback based fs API
if you want use fs/promise. First, you should open file to get a FileHandle. then you can use fileHanlde.createWriteStream().
import fs from 'fs/promises'
let file;
try{
file = await fs.open("example.png");
let ws = file.createWriteStream();
} finally(){
await file?.close();
}

Read files from a directory with a given path in JS

Is it possible to return the contents of a static path to a directory instead of using an .
I want to write a script that reads the contents of a directory on the file system to a given time daily. This is integrated in a webapp I can't edit.
Short answer: you can't.
You need to do this server-side. Here is an answer from a similar question, using node.js.
You can use the fs.readdir or fs.readdirSync methods.
fs.readdir
const testFolder = './tests/';
const fs = require('fs');
fs.readdir(testFolder, (err, files) => {
files.forEach(file => {
console.log(file);
});
});
fs.readdirSync
const testFolder = './tests/';
const fs = require('fs');
fs.readdirSync(testFolder).forEach(file => {
console.log(file);
});
The difference between the two methods, is that the first one is asynchronous, so you have to provide a callback function that will be executed when the read process ends.
The second is synchronous, it will return the file name array, but it will stop any further execution of your code until the read process ends.

how should I handle this nodejs code to do the rigth things?

this is my first question here. I need some help with my code structure. My api in node with express have to do the following:
receipt GET /api/file/{filename}
return the file content, its could be a big one (a few GB).
For now, I could get the files with streams, but I don't the best practice to handle error in this case.
'use strict';
const fs = require('fs');
const express = require('express');
const app = express();
const path = require('path');
const filePath = path.join(__dirname, `../file`);
console.log(filePath)
app.get('/api/:filename', (req, res) => {
let filename = req.params.filename
const streamFile = fs.createReadStream(`${filePath}/${filename}`);
streamFile.pipe(res);
} );
module.exports = app;
Should I make another dir, maybe 'modules', and there code an async function to read and pipe the files, and call the function from app.get in routes dir ?
Remember that Express is an "un-opinionated, minimalist web framework for Node.js applications", unopinionated means that it doesn't decide for you a lot of aspects of what tool you use for each specific task, and that is the main difference with another frameworks like Rails. Said that, you could use the classical and and old try and catch, in this case around your I/O operation. A module is a way to mantain separation of concerns and it's a way to organize your code so you can fastly identify what is the part of your code that is causing a malfunction. So in this case i don't consider it necessary because your router's callback is doing one thing and that is ok.
app.get('/api/:filename', (req, res) => {
let filename = req.params.filename
try{
const path = `${filePath}/${filename}`;
if (!fs.existsSync(path)) return res.status(404).send('You could send any message here...');
const streamFile = fs.createReadStream(path);
streamFile.pipe(res);
} catch {
res.status(500).send();
};
});

loadFrozenModel does not work with local files

need help with async/await.
currently studying https://github.com/tensorflow/tfjs-converter.
and I'm stumped at this part of the code (loading my python converted saved js model for use in the browser):
import * as tf from '#tensorflow/tfjs';
import {loadFrozenModel} from '#tensorflow/tfjs-converter';
/*1st model loader*/
const MODEL_URL = './model/web_model.pb';
const WEIGHTS_URL = '.model/weights_manifest.json';
const model = await loadFrozenModel(MODEL_URL, WEIGHTS_URL);
/*2nd model execution in browser*/
const cat = document.getElementById('cat');
model.execute({input: tf.fromPixels(cat)});
I noticed it's using es6 (import/export) and es2017 (async/await) so I've used babel with babel-preset-env, babel-polyfill and babel-plugin-transform-runtime. I've used webpack but switched over to Parcel as my bundler (as suggested by the tensorflow.js devs). In both bundlers I keep getting the error that the await should be wrapped in an async function so I wrapped the first part of the code in an async function hoping to get a Promise.
async function loadMod(){
const MODEL_URL = './model/web_model.pb';
const WEIGHTS_URL = '.model/weights_manifest.json';
const model = await loadFrozenModel(MODEL_URL, WEIGHTS_URL);
}
loadMod();
now both builders say that the 'await is a reserved word'. vscode eslinter says that loadMod(); has a Promise void. (so the promise failed or got rejected?)
I'm trying to reference the javascript model files using a relative path or is this wrong? I have to 'serve' the ML model from the cloud? It can't be from a relative local path?
Any suggestions would be much appreciated. Thanks!
tf.loadFrozenModel uses fetch under the hood. Fetch is used to get a file served by a server and cannot be used with local files unless those are served by a server. See this answer for more.
For loadFrozenModel to work with local files, those files needs to be served by a server. One can use http-server to serve the model topology and its weights.
// install the http-server module
npm install http-server -g
// cd to the repository containing the files
// launch the server to serve static files of model topology and weights
http-server -c1 --cors .
// load model in js script
(async () => {
...
const model = await tf.loadFrozenModel('http://localhost:8080/tensorflowjs_model.pb', 'http://localhost:8080/weights_manifest.json')
})()
You try to use this function
tf.loadFrozenModel(MODEL_FILE_URL, WEIGHT_MANIFEST_FILE_URL)
And your code has a syntax error. If you use the key words 'await', you must define one async function, such as below:
async function run () {
/*1st model loader*/
MODEL_URL = './model/web_model.pb';
const WEIGHTS_URL = '.model/weights_manifest.json';
const model = await loadFrozenModel(MODEL_URL, WEIGHTS_URL);
/*2nd model execution in browser*/
const cat = document.getElementById('cat');
model.execute({input: tf.fromPixels(cat)});
}
run();

TypeError: util.promisify is not a function?

I'm trying to promisify zlib.gunzip in my react application:
const zlib = require('zlib')
const util = require('util')
const gunzipPromisified = util.promisify(zlib.gunzip)
But I get this error:
TypeError: util.promisify is not a function
That works fine if I put it in a standalone script file and run it through node.
If I try:
import zlib from 'zlib'
import util from 'util'
const gunzipPromisified = util.promisify(zlib.gunzip)
I get something even fancier:
TypeError: __WEBPACK_IMPORTED_MODULE_8_util___default.a.promisify is not a function
What am I missing?
[Edit] The node.js version installed on my laptop is 8.9.1.
[Edit] As somebody commented, the node.js installed in my local development environment has nothing to do with what the app code has access to in the browser. So now my question is, how do I determine what API I have access to in the browser?
I had the same problem in Ionic. The util promisify didn't work for me either, and generated the same error as the one for OP. I ended up using this simple solution copied below:
const promisify = (fn) => {
return (...args) => {
return new Promise((resolve, reject)=>{
fn(...args, function(err, res){
if(err){
return reject(err);
}
return resolve(res);
})
})
}
}
And then:
const requestPromisified = promisify(request)
I had the same problem, it got fixed by updating Node to a version higher than Node 7.
n latest
In my case Node 9.2.0 as this was added later.
Of course everything works fine when I switch to bluebird's Promise.

Categories