I am using a node npm module in a next js app to get data from an api.
static async getInitialProps() {
const zxapi = new Zxapi(connectId, secretKey);
const res2 = await zxapi.programs({ region: "DE" }, function(err, result) {
if (err != null) {
return err
}
console.log(result, "before return");
return result
console.log(result, "after return");
});
return { res2 };
}
I need to return the values of res2. The "before return" console.log logs the data to the terminal and terminates there. What am I doing wrong? Thanks
Can you check if zxapi.programs returns a Promise? If it doesn't, you might have to create a function that makes it return a Promise.
For example, you can use something like
function zxpromise() {
return new Promise((resolve, reject) => zxapi.programs({ region: "DE" }, function(err, result) {
if (err != null) {
reject(err);
}
console.log(result, "before return");
resolve(result);
console.log(result, "after return");
}));
}
and then, you can call zxpromise as
const res2 = await zxpromise()
Related
I have a module for nodejs where i search mx records of email service, then i call a reduce to find the one with lowest priority (i will connect to this mx record to send a message) and then i need to save this value (exactly smtp.gmail.com) and pass it into my another module. What do i do wrong ?
const dns = require('dns');
async function getMX() {
return new Promise(function (resolve, reject) {
dns.resolveMx('gmail.com', function (err, addresses) {
if (err) {
resolve(null);
}
else {
resolve(addresses);
}
});
}).then(listOfMX => { // here i'm looking for value with lowest priority
return arr = listOfMX.reduce((previous, current) => {
if (previous.priority < current.priority) {
return previous
}
return current;
})
}).then(response => {
console.log(response[0]);
return response.exchange; // i get {exchange:"smtp.aspko.com", priority: 5}, and from this i return only the exchange
}).catch(err => {
console.log(err);
});
};
async function f() { // async function to solve the Promise <pending>
const response = await getMX();
console.log(response)
};
f(); // here i call the main function
Anyway i still see or Promise or undefined and i can't just add a return in async function f(), which will solve my problem (when i will call f() it should return me the one value, but instead i see undefined)
So, im my nodeJS project I have this part of my code, that is not waiting for the await call
Controller.js
exports.getList = async function(request, response) {
try {
const result = await useCase.getList()
if (result == undefined) {
utils.unavailable(response)
}
else if (result == null || result.length == 0) {
utils.respond(response, 404, errCodes.NOT_FOUND)
}
else utils.respond(response, 200, result)
}
catch(e) {
utils.unavailable(response)
}}
This is the function on the controller, it calls the response from the useCase
UseCase.js
exports.getList = async function() {
return await new Promise(function(resolve) {
resolve(repository.getList())
})
Which also calls the repository
Repository.js
exports.getList = async function() {
MongoClient.connect(Constants.DB_URL, function(err, db) {
if (err) {
console.log(err)
return undefined
}
const dbo = db.db(Constants.DB_NAME)
dbo.collection(Constants.DB_FEATURE1_COLLECTION).find({}).toArray(function(err, result) {
if (err) {
console.log(err)
return undefined
}
db.close()
return result
})
});
So, what happens is that on the controller, the result is always undefined, since result hasn't been initialized, when it should have actually waited for the response of the Promise on the UseCase. So what am I doing wrong?
getList function does not have return statement, and since it is async it returns a Promise that always resolves with undefined. I am not very familiar with MongoClient, but documentation says it returns a promise if no callback is specified. So you can change your code:
exports.getList = async function () {
try {
const db = await MongoClient.connect(Constants.DB_URL);
const dbo = db.db(Constants.DB_NAME);
const result = await dbo.collection(Constants.DB_FEATURE1_COLLECTION).find({}).toArray();
db.close();
return result
} catch (err) {
console.log(err);
return undefined
}
};
and UseCase.js:
exports.getList = function() {
return repository.getList(); // it returns a Promise there is no need to wrap it in async
};
I'm having issues with getting the result of a callback function. Below is the async function that I'm calling
const utils = {
sendQuery: async function(query){
// Receives a query and returns raw results
// Query is using default database specified by pool
// Returns a Promise
let conn;
try {
conn = await pool.getConnection();
let queryString = query;
let rows = await conn.query(queryString);
let results = (this.formatResults(rows));
console.log(results);
return results;
} catch(err) {
throw new Error(err);
} finally {
if (conn) return conn.end();
}
}
module.exports = {
'utils': utils
}
the console log above returns the expected result.
and below is the function that calls the above
const db = require('../private/db');
db.utils.sendQuery(queryString).then(function(result){
console.log(result);
}).catch(err=>{
throw res.render('error', {'error': err.stack});
})
the console log above returns undefined and I have no idea why.
The real problem here is this part if (conn) return conn.end();.
Whenever you are using finally, it will override any previous return, break, continue or throw that happens either in the stated try or catch blocks.
To fix your issue you should do like so:
const utils = {
sendQuery: async function(query){
// Receives a query and returns raw results
// Query is using default database specified by pool
// Returns a Promise
let conn;
try {
conn = await pool.getConnection();
let queryString = query;
let rows = await conn.query(queryString);
let results = (this.formatResults(rows));
console.log(results);
return results;
} catch(err) {
throw new Error(err);
} finally {
if (conn) conn.end();
}
}
module.exports = {
'utils': utils
}
Hope it works
In my opinion, just return results instead of resolve(results). Your function is already async and no promise object is created here.
And just throw err instead of reject(err);
And since you return in your try, you don't need your finally statement.
You need to simply return the result instead of calling resolve
const utils = {
sendQuery: async function(query){
// Receives a query and returns raw results
// Query is using default database specified by pool
// Returns a Promise
let conn;
try {
conn = await pool.getConnection();
let queryString = query;
let rows = await conn.query(queryString);
let results = (this.formatResults(rows));
console.log(results);
return results;
} catch(err) {
throw new Error(err)
} finally {
if (conn) return conn.end();
}
}
module.exports = {
'utils': utils
}
you could simply return or i suppose this is what you were trying to do
sendQuery: (query) => {
let promise = new Promise(async (resolve, reject) => {
let conn;
try {
conn = await pool.getConnection();
let queryString = query;
let rows = await conn.query(queryString);
let results = (this.formatResults(rows));
console.log(results);
resolve(results);
} catch (err) {
reject(err);
} finally {
if (conn) {
conn.end();
}
}
})
return promise;
}
I want to save sqlite3 row values into an array. I followed what was discussed here:
Can't put rows into array using sqlite3 on Node.js
However when I console.log my would-be-array records, I obtain:
console.log(records) => an array with values [1,1,2]
console.log(records[1]) => undefined
There must be a mistake in my understanding of what's going on. What is wrong?
Full code below:
const sqlite3 = require('sqlite3').verbose();
let db = new sqlite3.Database('src/db/ksbib.db', (err) => { if (err) { return console.log(err.message); } });
let result = [];
let records = [];
function catchResult (err, row)
{
if (err) { return console.log(err.message); }
else { return result.push(row.objektid); }
}
function getData ()
{
return new Promise ((resolve, reject) =>
{
db.parallelize ( () =>
{
db.each(sqlTitel(param), catchResult);
db.each(sqlAutor(param), catchResult);
});
resolve(result);
})
}
async function res ()
{
records = await getData();
console.log(records);
console.log(records[1]);
return records;
};
let x = res();
console.log(x);
The contradiction between console.log(records) and console.log(records[1]) does not exist in the commandline. It seems that some other code interferes in the console.
Moreover, the promise as implemented above resolves with the emtpy result-array before the database request is finished. One can introduce a timeout to play with the code.
In order to resolve the promise after the database request, one should resolve it in the callback function of the request. That's also the reason why db.all is much easier to handle than db.each.
Instead of a series of database requests one can then use a series of promises. Thereby it is important to wait for every single promise to be resolved (just coupling them like this return await sqr(sqlTitle(y), []).then(sqr(sqlAuthor(y), [])) gives no unique result). The result-array is completed bit by bit.
const sqlite3 = require('sqlite3').verbose();
let db = new sqlite3.Database('ksbib.db', (err) => { if (err) { return console.log(err.message); } });
let result = [];
let p;
function sqr (sql, x)
{
return new Promise(function (resolve, reject)
{
db.all(sql, x, (err, rows) =>
{
if (err) {
reject(err);
} else {
rows.forEach( (row) => {result.push(row.objektid)} );
resolve(result);
}
});
});
}
( async () =>
{
p = await sqr(sqlTitle(y), []);
p = await sqr(sqlAuthor(y), []);
return p; //the final result
})();
I try find one item by name, then update table and return updated result, but return didn't work. My code:
class addSongsToArtist {
constructor(artistName) {
Artist.findOne({
name: artistName
}).exec((err, data) => {
if (err) console.log(err);
data.name = 'updated name'
data.save();
return data // * not work
});
}
}
Into exec method I see data with correct result, and into mongo console result saved. But return not works. I tried save changes into external variable and return result in Promise, but it not work too.
Why it not works?
You use .save async function as sync function, try this instead :
constructor(artistName) {
Artist.findOne({
name: artistName
}).exec((err, data) => {
if (err || !data){
console.log(err);
return null;
}
else
{
data.name = 'updated name'
data.save(function(err, savedDatas)
{
if(err || !savedDatas)
{
return null;
}
else
{
return savedDatas; // * not work
}
});
}
});
I have solution. Problem with construct method which return new object instance.
Worked code:
class addSongsToArtist {
constructor(artistName) {
this.result = false
Artist.findOne({
name: artistName
}).exec((err, data) => {
if (err) console.log(err);
data.name = 'updated name'
data.save();
this.result = data
});
}
/**
* need call in promise after call new addSongsToArtist()
*/
getData() {
return this.result
}
}
And get data:
let findOne;
Promise.resolve()
.then(()=>{
findOne = new addSongsToArtist()
})
.then(()=>{
findOne.getData()
});