Node.Js promises and async/await - node.js

I am trying to use a oai-pmh harvester to harvest all articles from oai repositor and store them in a local mongo database.
I have a small demo.js file to test and print the titles on the console and it works perfectly. This is my demo.js file:
const oaipmh = require('./my_modules/harvester/harvester.js');
const urlProvider='any OAI URL repo'; // change URL here
let harvester=new oaipmh.Harvester(urlProvider);
harvester.harvest(processItem,function(err,res){
console.log(res);
});
Function processItem(item){
try{
let titles=item.metadata['oai:dc:dc']['dc:title'];
let title=(typeof titles=='object')?titles.join("\n"):titles;
console.log(title);
console.dir(item.metadata['oai_dc:dc']);
}catch(err){
// handle errors here
}
};
I am still trying to learn how to use promises and async/await and how to handle it. So far I have tried to use it inside my controller, but I am getting an error.
On my router file i have:
router.route('/doc')
.get(doc.aggregate_one);
On my controller file i have:
var Doc=require('../models/docModel);
const aoipmh=require('../../harvester/harvester');
exports.aggregate_one = async (req,res,next) => {
const urlProvider = req.header('url');
let harvester=new oaipmh.Harvester(urlProvider);
harveste.harvestAsync(urlProvider,processItemmfunction(err,res){
// do something
});
};
I want to send the URL in the header of my get instead of the barcode. When I am trying to test the GET I am receiving an UnhandledPromiseRejectionWarning: Error; Unexpected status code 400 (expected 200)
How can I use the example of the demo.js file inside my controller in order to handle the Promise?

Related

How to get a mapped Url in Vite? Source map

I have not yet entered the world of plugins, but I have one idea and I want to test it as simple as possible.
Question:
I have a url WITHOUT SOURCE MAP, e.g. instance/$$self.$$.update#http://localhost:5173/src/lib/ContextListItem.svelte:448:15.
And I want to get from it a URL WITH SOURCE MAP, e.g. http://localhost:5173/src/lib/ContextListItem.svelte:19:11.
Theoretically it is a simple function:
const mappedUrl = getMappedUrl(url)
How to get it in Vite?
What do I need it for?
I have such code:
window._log = console.log.bind(console);
console.log = function (...a) {
try {
throw Error("aa");
} catch (err) {
const fileUrl = err.stack.split("\n")[1].split("#")[1].replace(`${location.origin}/`,"").split(":")[0];
window._log(...a, `${location.origin}/__open-in-editor?file=${/* encodeURIComponent */(fileUrl)}`);
}
}
And I want (as you can see) to add a link to the location in the code (thanks to the method from __open-in-editor).
Here I am missing a specific line and column in the file.
In Microsoft Egde any link from the console can direct to VSCode, but unfortunately in other browsers this is not there (e.g. my bug for Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=1771862).
This is the answer, But it only works asynchronously, so it's not suitable for replacing console.log. :/
Use on the Web - https://github.com/mozilla/source-map/#use-on-the-web
Consuming a source map - https://github.com/mozilla/source-map/#consuming-a-source-map
<script src="https://unpkg.com/source-map#0.7.3/dist/source-map.js"></script>
<script>
sourceMap.SourceMapConsumer.initialize({
"lib/mappings.wasm": "https://unpkg.com/source-map#0.7.3/lib/mappings.wasm"
});
</script>
<script type="module">
export async function aaa (origin, fileUrl, line, column) {
const res = await fetch(`${origin}/${fileUrl}.map`);
const json = await res.json();
const place = await sourceMap.SourceMapConsumer.with(json, null, consumer => {
const place = consumer.originalPositionFor({
line: Number(line),
column: Number(column)
});
return place;
});
return place;
}
</script>

NodeJS Passing Express res to completely different module

I have an program that susposed to load js to server side dynamically by url (for organizing js files)
app.get('/*',function(req,res){
... path etc. code
if(compare(list,path)){
const js = require('/Js/'+list.find(x => x.pageUrl == path).js)
js.run(req,res)
}
... more code there
}
but for some reason passed res doesnt work and i get res.send is not defined error
here is the other module that i get path from url and load it
exports.run = function run(req,res)
{
res.Send("test") //not defined for some reason
console.log(res) //it is not undefined, i see stuff
res.end()
}
Your code says res.Send instead of res.send.

TypeError: invNum.next is not a function

I have tried this code :
const invNum = require('invoice-number');
router.post('/checkout', async (req, res, next) => {
if (!req.session.cart) {
return res.redirect('/pos/');
}
var saleList = Sale.find().sort({ _id: -1 }).limit(1); // removed (err, data)=>{} to simply view it is working tested already
var settings = await Setting.find({}); // removed try and catch to simply view it is working tested already
var ticketNumber;
ticketNumber = !saleList ? invNum.next('0000000') : invNum.next(saleList.ticket_number);
var sale = new Sale({
ticket_number:ticketNumber,
cart: req.session.cart,
created_at: new Date()
});
sale.save((err, product) => {
createReceipt(settings, req.session.cart, "receipts/"+ticketNumber+".pdf");
req.session.cart = null;
res.redirect('/pos/');
});
});
I got this error:
TypeError: invNum.next is not a function
The problem is with invNum.next().
invNum.next() is a Node.js module to generate invoice number sequentially installed from npm.
Example:
invNum.next('2017/08/ABC001')
// => 2017/08/ABC002
I have tried already suggestions from previous stackoverflow posts by trying Promises or await async function in order to get this code to work. Hopefully, you can help or suggest something. Thank you.
There is a problem in version of invoice-number module. In the npm it is showing as 1.0.6 but in the GitHub repository it has 1.0.5 in the package.json file.
https://github.com/amindia/invoice-number.
I have tested this module by taking from Github repository and it's working fine.
Please take the source of this module from the given link it will works fine.
Seems to be some error in the module. I tried the below code snippet on RunKit
https://runkit.com/embed/ws2lv1y38mt4
var invNum = require('invoice-number')
try{
invNum.next('sdfsd1')
} catch(e){
console.log(e)
}
Getting the same error
I got this error:
TypeError: invNum.next is not a function UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch()
What is the output when you use the console.log on invNum?
Also use try catch and inside call invNum.next with await. Maybe something inside this function is throwing an error.
Edit: as jfriend00 says, if an plain text (like your "0000...") is working, probably the saleList is returning some error and you are not catching or treating the error.
Edit2: The last update on this NPM code is from 1 year ago and fewer people used this lib, probably is broken.
There is some part of the code from the index.js of the lib:
function _next (invoiceNumber) {
if (!invoiceNumber)
throw new Error('invoiceNumber cannot be empty')
var array = invoiceNumber.split(/[_/:\-;\\]+/)
var lastSegment = array.pop()
var priorSegment = invoiceNumber.substr(0, invoiceNumber.indexOf(lastSegment))
var nextNumber = alphaNumericIncrementer(lastSegment)
return priorSegment + nextNumber}
var api = { next: _next}
module.exports = api

Is it possible to module.exports a local variable from async function?

I have this async function in a file called index.main.js which has a variable , 'targetFiles' which I would like to export to another file which is index.js. Problem is I can't find a way to export the value of this particular variable without getting "undefined" as a result.
I have tried implementing promise, callback , export default function, and doing countless hours of research to no avail.
//this code is in index.main.js
var targetFiles = "";
async function listFilesInDepth()
{
const {Storage} = require('#google-cloud/storage');
const storage = new Storage();
const bucketName = 'probizmy';
const [files] = await storage.bucket(bucketName).getFiles();
console.log('List Of Files Available:');
files.forEach(file =>
{
targetFiles = file.name; //this is the variable to export
console.log(`-----`+file.name);
});
return targetFiles;
}
module.exports = {
fn : targetFiles
}
trying to export the value to index.js is either empty or "undefined"
//this is the code in index.js
const a = require('./index.main');
console.log(a.fn); //undefined or empty
The expected value that should be the output is the value of targetFiles. Let's say if targetFiles is abc12345.JSON in the async function,the console.log in index.js should be of that value.
I'm hoping someone could give me some insight on how I could overcome this issue. Thank you in advance :)
Following solution might help you, but not sure for your use case. (Not using module-exports):
You can use request-context package to achieve same functionality.
What is package does is, you can set the value(data) against a key and then access the same in the following code execution within the same context.
Run npm install request-context
In your main app.js (server file), register the request-context as a middleware.
const contextService = require("request-context");
const app = express();
...
// Multiple contexts are supported, but below we are setting for per request.
app.use(contextService.middleware("request"));
...
And then in your index.main.js, once targetFiles is ready, set the targetFiles into request context.
const contextService = require("request-context");
...
files.forEach(file =>
{
targetFiles = file.name; //this is the variable to export
console.log(`-----`+file.name);
});
// Here `Request` is the namespace(context), targetFileKey is the key and targetFiles is the value.
contextService.set("request:targetFileKey", targetFiles);
return targetFiles;
}
...
And in the same request, where you wanna use targetFile, you can do the following:
index.js (Can be any file where you need targetFiles after being set):
const contextService = require("request-context");
...
// Reading from same namespace request to which we had set earlier
const targetFiles = contextService.get("request:targetFileKey");
...
Please note:
You will be able to access targetFiles in the same request you set. That means, request-context we configured in app.js is per API request, meaning, in every API request, you have to set it before reading.
Please let me know if the above solution doesn't fit for you.

Why am I getting a NOENT using Node core module 'fs'

This a repeat question (not yet answered) but I have revised and tightened up the code. And, I have included the specific example. I am sorry to keep beating this drum, but I need help.
This is a Node API. I need to read and write JSON data. I am using the Node core module 'fs', not the npm package by the same name (or fs-extra). I have extracted the particular area of concern onto a standalone module that is shown here:
'use strict';
/*==================================================
This service GETs the list of ids to the json data files
to be processed, from a json file with the id 'ids.json'.
It returns and exports idsList (an array holding the ids of the json data files)
It also calls putIdsCleared to clear the 'ids.json' file for the next batch of processing
==================================================*/
// node modules
const fs = require('fs');
const config = require('config');
const scheme = config.get('json.scheme')
const jsonPath = config.get('json.path');
const url = `${scheme}${jsonPath}/`;
const idsID = 'ids.json';
const uri = `${url}${idsID}`;
let idsList = [];
const getList = async (uri) => {
await fs.readFile(uri, 'utf8', (err, data) => {
if (err) {
return(console.log( new Error(err.message) ));
}
return jsonData = JSON.parse(data);
})
}
// The idea is to get the empty array written back to 'ids.json' before returning to 'process.js'
const clearList = async (uri) => {
let data = JSON.stringify({'ids': []});
await fs.writeFile(uri, data, (err) => {
if (err) {
return (console.log( new Error(err.message) ));
}
return;
})
}
getList(uri);
clearList(uri)
console.log('end of idsList',idsList);
module.exports = idsList;
Here is the console output from the execution of the module:
Error: ENOENT: no such file or directory, open 'File:///Users/doug5solas/sandbox/libertyMutual/server/api/ids.json'
at ReadFileContext.fs.readFile [as callback]
(/Users/doug5solas/sandbox/libertyMutual/server/.playground/ids.js:24:33)
at FSReqWrap.readFileAfterOpen [as oncomplete] (fs.js:235:13)
Error: ENOENT: no such file or directory, open 'File:///Users/doug5solas/sandbox/libertyMutual/server/api/ids.json'
at fs.writeFile
(/Users/doug5solas/sandbox/libertyMutual/server/.playground/ids.js:36:34)
at fs.js:1167:7
at FSReqWrap.oncomplete (fs.js:141:20)
I am being told there is no such file or directory. However I can copy the uri (as shown in the error message)
File:///Users/doug5solas/sandbox/libertyMutual/server/api/ids.json
into the search bar of my browser and this is what is returned to me:
{
"ids": [
"5sM5YLnnNMN_1540338527220.json",
"5sM5YLnnNMN_1540389571029.json",
"6tN6ZMooONO_1540389269289.json"
]
}
This result is the expected result. I do not "get" why I can get the data manually but I cannot get it programmatically, using the same uri. What am I missing? Help appreciated.
Your File URI is in the wrong format.
It shouldn't contain the File:// protocol (that's a browser-specific thing).
I'd imagine you want C://Users/doug5solas/sandbox/libertyMutual/server/api/ids.json.
I solved the problem by going to readFileSync. I don't like it but it works and it is only one read.

Resources