Promises function Use in Nodejs - node.js

Can't able to understand the promise function, how to deal with it can anyone explain it through a simple example. Tried it through different sites but got confused in it

You can understand it with this example:
const request = require("request")
function doSomething(url){
//return promise from here
return new Promise(function(resolve, reject) {
request.get(url, function(error, resp, body) {
if (error) {
reject(error);
} else {
resolve(JSON.parse(body));
}
})
})
}
function callDoSomething(){
//initialising a promise
let prom = doSomething(url)
//consume it
prom.then(function(res) {
console.log(res)
})
.catch(function(e){
console.log(e.message)
})
}
callDoSomething()
You can also go for Promise.all to deal with multiple promise:
let prom1 = doSomething(url1)
let prom2 = doSomething(url2)
let prom3 = doSomething(url3)
Promise.all([prom1,prom2,prom3])
.then(res =>{
//expected output array
console.log(res)
})
.catch(e =>{
console.log(e.message)
})

A Promise is a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers to an asynchronous action's eventual success value or failure reason. This lets asynchronous methods return values like synchronous methods: instead of the final value, the asynchronous method returns a promise for the value at some point in the future.
In simple words “A promise is a word taken for some action, the other party who gave the promise might fulfill it or deny it”. In the case of fulfilling, the promise gets resolved, and in another case, it gets rejected.
We can create a promise in JavaScript and use it as an upcoming fact to describe few actions. Promises are kind of design patterns to remove the usage of unintuitive callbacks.

Related

the piece of code will not executed in async wait

the piace of code with if condition will not executed and the parent function will be executed after promise, but I dont understand why
let sql = `SELECT *
FROM ${table}
WHERE trader = '${trader}'
AND pair = '${data.symbol}'`;
console.log(sql)
let resp = await new Promise((resolve, reject) => {
db.all(sql, function (err, rows) {
console.log("err2")
console.log(err)
console.log("rows2")
console.log(rows)
return resolve(rows)
})
})
if (resp[0]) { // <------- this will be executed after
if (data.amount > resp[0].amount) {
console.log('amount cambiato, comprato')
// BUY Position
await updatePosition(data, trader, 'buy');
}
if (data.amount < resp[0].amount) {
console.log('amount cambiato, sellato')
// BUY Position
await updatePosition(data, trader, 'sell');
}
if (data.amount == resp[0].amount) {
// BUY Position
console.log('amount IDENTICO');
await setCheckedTraderCoin(trader, data.symbol)
}
}
why this?
This has to be in an async function since you're using await. Thus, it returns a promise.
So, the caller must use await or .then() on that returned promise so it will also wait for the work to be done here.
ALL async functions return their promise upon the first await in the function. That's why the caller has to also wait for that promise to resolve - otherwise it runs off and executes before any of the asynchronous work in this function is complete (as you've observed).
So, the solution to your caller running before the asynchronous work in this function has completed is for the caller to wait (using either .then() or await) for the returned promise to resolve before it does anything further.
Also, you need error handling on the promise that wraps db.all() so you reject that promise if there's an error:
let resp = await new Promise((resolve, reject) => {
db.all(sql, function (err, rows) {
if (err) {
reject(err);
} else {
resolve(rows)
}
});
});
FYI, it would be preferable to use a driver for your database that directly supports promises so you don't have to manually wrap each call in a promise yourself. Most database interfaces support promises by now. Sometimes, you need a different version of the driver - sometimes it's already available in the one you're using. It depends upon which database/driver you are currently using.

Node.js Promise.all when function returns nothing

How to handle multiple calls to the same function when its returning nothing. I need to wait untill all calls are finished so i can call another function.
For now I'm using Promise.all() but it doesn't seem right:
Promise.all(table_statements.map(i => insertValues(i)))
.then(function(result) {
readNodeData(session, nodes);
})
.catch(function() {
console.log(err);
})
function insertValues(statement) {
return new Promise((res, rej) => {
database.query(statement, function (err, result) {
if (err) {
rej(err)
}
else{
console.log("Daten in Tabelle geschrieben")
res(); // basically returning nothing
}
});
});
}
This writes data to a database in multiple statements, i need to wait untill all are finished.
Is this actually the "right" way to do it? I mean... it works, but i have the feeling it's not how you are supposed to do it.
Using Promise.all for your case is a good call, since it returns a Promise, when all the promises passed as an iterable are resolved. See the docs.
However, for brevity and readability, try converting your insertValues into async-await function as follows. This tutorial would be a great place to start learning about async functions in JavaScript.
// async insertValues function - for re-usability (and perhaps easy unit testing),
// I've passed the database as an argument to the function
async function insertValues(database, statement) {
try {
await database.query(statement);
} catch (error) {
console.error(error);
}
}
// using the insertValues() function
async function updateDatabase(database) {
try {
// I am using 'await' here to get the resolved value.
// I'm not sure this is the direction you want to take.
const results = await Promise.all(
tableStatements.map(statement => insertValues(database, statement))
);
// do stuff with 'results'.. I'm just going to log them to the console
console.log(results);
} catch (error) {
console.error(error);
}
}
Here, insertValues() function doesn't return any value. Its operation on the database is entirely dependent on the query statement passed to it. I wrapped it within a try-catch block so as to catch any errors that might arise while performing the operation (s) above. More details on handling errors using try-catch can be found here.
Your promisified write to database looks ok, so we can update code from another part.
Let's rewrite it a little to use async/await and try/catch.
(async() => {
const promisifiedStatements = table_statements.map(i => insertValues(i));
try {
await Promise.all(promisifiedStatements);
readNodeData(session, nodes);
} catch(e){
console.log(e)
}
})();
I use here IIFE to use await behaviour.

node.js middleware making code synchronous

I am trying to make res.locals.info available on every single page.
I'm trying to do this by middleware but I'm getting an error.
Apparently res.locals.info is not ready yet when the page render, thus I get an error info is not defined. How do I solve this?
app.use(function(req,res,next){
async function getInfo(user) {
let result = await info.search(user);
setInfo(result);
}
function setInfo(result){
res.locals.info= result;
}
getInfo(req.user);
return next();
})
search():
module.exports.search= function (user) {
var query=`SELECT count(*) as Info from dbo.InfoUsers WHERE user= '${user}' ;`
return new Promise((resolve, reject) => {
sequelize
.query(`${query}`, {model: InformationUser})
.then((info) => {
resolve(info);
})
})
};
You were calling next() before your getInfo() function had done its work, thus res.locals.info had not yet been set when you were trying to use it.
An async function returns a promise. It does NOT block until the await is done. Instead, it returns a promise immediately. You will need to use await or .then() on getInfo() so you know when it's actually done.
If info.search() returns a promise that resolves to the desired result, then you could do this:
app.use(function(req,res,next){
// this returns a promise that resolves when it's actually done
async function getInfo(user) {
let result = await info.search(user);
setInfo(result);
}
function setInfo(result){
res.locals.info= result;
}
// use .then() to know when getInfo() is done
// use .catch() to handle errors from getInfo()
getInfo(req.user).then(result => next()).catch(next);
});
And, you can remove the deferred anti-pattern from your search function and fix the error handling (which is a common issue when you use the anti-pattern). There is no need to wrap an existing promise in another promise.:
module.exports.search = function (user) {
var query=`SELECT count(*) as Info from dbo.InfoUsers WHERE user= '${user}' ;`
// return promise directly so caller can use .then() or await on it
return sequelize.query(`${query}`, {model: InformationUser});
};

await inside async controller function [duplicate]

I am working on a simple TCP client for a server and am using the latest node 7.6 because of the async/await functions. I'm new to node and asynchronous coding, so I apologize if this is stupidly easy.
I want to run a function that calls the callServer() function with specific parameters, wait until it finishes getting the data, and return the data as a variable.
Here is my code:
'use strict'
const net = require('net')
var formattedJson = funcRequestToJson("Server.GetStatus", false)
doThings()
async function doThings() {
var info = await callServer()
}
async function callServer() {
var client = new net.Socket()
client.connect(1705, '192.168.28.16', () => {
console.log('connected to server')
client.write(formattedJson)
})
client.on('data', (data) => {
client.destroy()
//return await data
console.log(data.toString())
})
client.on('close', () => {
})
}
// method and paramBool are always required
// macAddress, paramKey, paramValue are required for if paramBool is true
function funcRequestToJson(method, paramBool, macAddress, paramKey, paramValue) {
var objectRequest = {}
objectRequest[ "jsonrpc" ] = "2.0"
objectRequest[ "method" ] = method
objectRequest[ "id" ] = 0
if (paramBool == true) {
objectRequest[ "params" ] = {
"client": macAddress,
[paramKey]: paramValue
}
}
var json = (JSON.stringify(objectRequest) + '\r\n')
return json
}
So I didn't declare objectRequest() as async because it's not waiting on the server, but I think callServer() should be async, right? I know this can be done with promises, but I wanted to use async/await and this seems to be right.
Now, I want to return the data that comes from inside callServer() and client.on('data', (data) but I can't seem to figure out how to do it asynchronously. I would think there'd be a way to make an async function and call it with await like I tried (await return data) but it never works right.
I'm sorry if this is terribly convoluted, but I've been poring over async node tutorials for the past week and am still stuck.
Thanks!
Async/Await relies on code that uses promises for async operations. So you need to return a promise from any async operation in order to use it with async/await.
So, callServer() needs to return a promise that is resolved when the async operation inside it is done. In fact, you can only await an async operation in a function if that function returns a promise. await saves you from having to write .then() handlers on promises, but async/await does not magically know when async operations are done. You still have to wrap them in promises.
Here's an example of how you could make callServer() return a promise:
async function callServer(formattedJson) {
return new Promise((resolve, reject) => {
let client = new net.Socket()
client.connect(1705, '192.168.28.16', () => {
console.log('connected to server')
client.write(formattedJson)
})
client.on('data', (data) => {
resolve(data);
client.destroy()
})
client.on('close', () => {
})
client.on('error', reject);
});
}
Sample Usage:
try {
var info = await callServer(funcRequestToJson("Server.GetStatus", false));
} catch(e) {
// error here
}
Just to show you what await is doing, in ES5 (without async/await), the sample usage would be this:
callServer(funcRequestToJson("Server.GetStatus", false)).then(info => {
// info is available here
}).catch(err => {
// error here
});
So, await is just letting you avoid writing the .then() handler. Internally in the execution of the code, there's just a promise that the interpreter sets up a .then() handler for so it will know when that promise is resolved. This is syntactical sugar, not really any magic with async operations. You still have to use promises for all your async operations. You can use await instead of .then() and your code will appear more sequential even though it's really the same under the covers.
People think that await allows one to write asynchronous code as if it was synchronous, but that isn't really the case, especially if you handle errors and understand concurrency issues. It will look more synchronous, but isn't actually any more synchronous than it was with .then() in ES5.
And, watch out for error handling. In people's quest to write synchronous looking code, people seem to completely forget to handle rejected promises in their async operations (which are handled with try/catch when using await). I'm personally not yet convinced that ES6 is a step forward when it comes to error handling as the early indications are that ES6 seems to encourage people to just forget about error handling or get lazy and not do it, whereas it's easier when using .then() to just know that there should be a .catch() somewhere for it to be solid code. Maybe that's just a learning process, but it seems to be an early issue when people use await.

Promise with res.send();

I'm using phantomjs with phridge for correct sharing pages for single page app.
Here's some code example:
if (isbot(req.headers['user-agent'])){
var url= req.protocol+'://'+req.get('host')+ req.originalUrl
phridge.spawn()
.then(function (phantom) {
var page = phantom.createPage();
return page.run(url, function (url, resolve, reject) {
var page = this;
page.open(url, function (status) {
// handle page after load
});
})
.then(function (contnt) {
res.send(contnt);
})
.then(phridge.disposeAll());
.catch(function (err) {
console.error(err.stack);
})
}
else {
next();
}
The question is - how the mechanic res.send() works with promise? Will be phridge.disposeAll() performed?
You are making numerous mistakes. You should make sure you are familiar with Promise style programming before writing these code. See the last section.
In this case, no, because the
.then(function (contnt) {
res.send(contnt);
})
part is not returning a Promise.
In this part, if you are sure res.send will not raise any exception, you could write:
.then(function (contnt) {
res.send(contnt);
return new Promise()
})
And the later part,
.then(phridge.disposeAll())
Is also problematic, you should modify it to be
.then(() => phridge.disposeAll())
even if it is the end of the chain and there is no use of create a new Promise, you should write it this way, because then() function takes functions, not result, to be its argument.
And you need to make sure each .then() branch returns a Promise like object while you are chaining them. (I did not check the others since I don't know what they returns.)
OK, there are more errors, I have seen redundant ; after then() branch. I am not sure if there are more problems.
I think the problem is more serious: you are not understanding Promise style programming. You should read the ES6 Promise docs, or Promise library (like bluebird, depends on which library your library depends on) docs closely first.
I would combine the res.send and disposeAll(). No need to over complicate the code.
res.send is synchronous and returns a boolean.
phridge.spawn()
.then(function (phantom) {
var page = phantom.createPage();
return page.run(url, function (url, resolve, reject) {
var page = this;
page.open(url, function (status) {
// handle page after load
});
})
.then(function (contnt) {
res.send(contnt);
phridge.disposeAll()
})
.catch(function (err) {
console.error(err.stack);
})

Resources