Promise not getting resolved while sending http request - node.js

I am calling func2(which should return promise) but promise is not getting resolved.Am I resolving promise wrongly or is there any other problem.Please let me know what is the problem in following code?
function func1() {
func2().then(function (data) {
console.log(data);
})
}
var func2 = function () {
var d = q.defer();
var postRequest = {
host: "abc",
path: "/xyz",
};
var buffer = "";
var req = http.request( postRequest, function( res ) {
var buffer = "";
res.on( "data", function( data ) {
console.log("data\n");
buffer = buffer + data;
});
res.on( "end", function( data ) {
d.resolve(data);
return d.promise;
});
});
console.log('after req');
req.write(body);
req.end();
};

You need to return the promise at the very end of the function. Try
function func1() {
func2().then(function (data) {
console.log(data);
}).catch(function (error) {
// Handle any error from all above steps
console.log("Got error:" + error);
})
.done();
}
var func2 = function () {
var d = q.defer();
var postRequest = {
host: "abc",
path: "/xyz",
};
var buffer = "";
var req = http.request( postRequest, function( res ) {
var buffer = "";
res.on( "data", function( data ) {
console.log("data\n");
buffer = buffer + data;
});
res.on( "end", function( data ) {
d.resolve(buffer);
});
res.on( "error", function( err ) {
d.reject(err);
});
});
console.log('after req');
req.write(body);
req.end();
return d.promise;
};

Related

Await function to finish calling another API

I am new to using async/await and having a couple issues.
I have the code below, which seems to not wait until the previous function is finished?
var url = require('url');
var path = require('path');
var https = require('https');
var request = require('request');
var url1 =
var url2 =
var url3 =
module.exports = async function (context, req) {
var call = await callUrl(context, url1);
context.log(call);
var call2 = await callUrl(context, url2);
context.log(call2);
var call3 = await callUrl(context, url3);
context.log(call3);
};
function callUrl (context, web) {
var requestUrl = url.parse(web);
const requestOptions = {
hostname: requestUrl.hostname,
path: requestUrl.path,
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
};
var request = https.request(requestOptions, function(res) {
var data = "";
res.on('data', function (chunk) {
data += chunk;
});
res.on('end', function () {
var jsonData = JSON.parse(data);
return jsonData;
});
}).on('error', function(error) {
context.log("request error:", error);
return context.done();
});
request.end();
}
I am trying to get call to happen, then when it is finished call2, then when that is finished call3.
Can someone pinpoint why this does not occur? Currently, it hits all 3 pretty much asap, and each context.log is undefined presumably because the endpoints don't return anything. Each url is another azure function app API I have created.
There is nothing I am requiring to return from each call to use, I simply want them to finish before moving on the the next function.
Your callUrl method, which you call with await, needs to be either async itself or return a Promise. Why? because the work it does is itself asynchronous.
Here's your function adapted to use a Promise and return its actual value via the resolve() callback.
function callUrl (context, web) {
var requestUrl = url.parse(web);
const requestOptions = {
hostname: requestUrl.hostname,
path: requestUrl.path,
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
};
return new Promise(function (resolve,reject) {
var request = https.request( requestOptions, function( res ) {
var data = "";
res.on( 'data', function( chunk ) {
data += chunk;
} );
res.on( 'end', function() {
var jsonData = JSON.parse( data );
resolve( jsonData );
} );
} )
.on( 'error', function( error ) {
reject(error);
} );
request.end();
});
}
Notice that you use a POST operation with no body. That's a little unconventional.

How to just pass an object in post method and just retrieve it as such?

We are using method called flask_api which has the parameter.
Our need is, we need to pass that parameter inside request.post
Can anyone please help as we are beginners in node.js
async flask_api(turnContext){
var res;
var fs = require('fs');
var request = require('request');
var formData = {image1: fs.createReadStream('D:/my_app/demo.png')}
var json_body = "" ;
var obj_value= ""
function initPromise(turnContext)
{return new Promise(function(resolve,reject)
{
console.log("print turn context",turnContext); //we are getting the value in turncontext
console.error('before post call...:1');
request.post({url:'http://127.0.0.1:5002/',formData: formData}, function(err, httpResponse, body)
{
if (err) {
console.log("response", reject(err));
return JSON.stringify(err);
}
else{
while(1==1){
if(body != undefined){
break;
}
}
json_body = JSON.parse(body);
resolve([json_body,turnContext]);//here we are not able to get the turncontext
}
});
})
}
Try using this:
var req = request.post({ url: 'http://127.0.0.1:5002/' }, (err, resp, body) => {
if (err) {
res.status(500).send(err);
} else {
res.send(resp);
}
});
var form = req.form();
form.append('file', fs.createReadStream('D:/my_app/demo.png'));
In your case:
async flask_api(turnContext){
var res;
var fs = require('fs');
var request = require('request');
var formData = {image1: fs.createReadStream('D:/my_app/demo.png')}
var json_body = "" ;
var obj_value= ""
var tempContext;
function initPromise(turnContext)
{return new Promise(function(resolve,reject)
{
tempContext = turnContext;
console.log("print turn context",tempContext); //we are getting the value in turncontext
console.error('before post call...:1');
request.post({url:'http://127.0.0.1:5002/',formData: formData}, (err, httpResponse, body) =>
{
if (err) {
console.log("response", reject(err));
return JSON.stringify(err);
}
else{
while(1==1){
if(body != undefined){
break;
}
}
json_body = JSON.parse(body);
resolve([json_body,tempContext]);//here we are not able to get the turncontext
}
});
})
}
Try this. Note that I refactored your code (how I would have done it).
Server (for test purposes)
var http = require('http');
var querystring = require('querystring');
var server = http.createServer().listen(8124);
server.on('request', function(request,response) {
if (request.method == 'POST') {
var body = '';
// append data chunk to body
request.on('data', function (data) {
body += data;
});
// data transmitted
request.on('end', function () {
var post = querystring.parse(body);
console.log(post);
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end(JSON.stringify('body\n'));
});
}
});
console.log('server listening on 8124');
Client
function initPromise(turnContext) {
var res;
var fs = require('fs');
var request = require('request');
var formData = {image1: "hello"}
var json_body = "" ;
var obj_value= "";
return new Promise(function(resolve,reject) {
console.log("print turn context",turnContext); //we are getting the value in turncontext
console.error('before post call...:1');
request.post({url:'http://localhost:8124/',formData: formData}, function(err, httpResponse, body) {
if (err) {
reject(err);
}
else{
if (body != undefined) {
json_body = JSON.parse(body);
resolve([json_body,turnContext]); //here we are not able to get the turncontext
} else {
reject('body undefined');
}
}
});
});
}
async function flask_api(turnContext) {
var result = initPromise(turnContext);
console.log("result", result);
result.then(
// fulfillment
function (val) { //this is where you get the value passed to resolve()
console.log(val);
}).catch(
//log the rejection reason
(reason) => {
console.error(reason);
}
);
}
flask_api({test: 'hello'});
The result on the client side is:
print turn context { test: 'hello' }
before post call...:1
result Promise { <pending> }
[ 'body\n', { test: 'hello' } ]
Note:
That line of code return JSON.stringify(err); isn't necessary. The callback in a promise is not expecting any return unless you want to use it for flow control purposes.
if body is indeed undefined, you will have an infinite loop.
Try using this:
This will work for the latest node.js versions.
async initPromise(turnContext)
{
var res;
var fs = require('fs');
var request = require('request');
var formData1 = {image1: "Hello"};
var path = require('path')
var base_dir=path.dirname(path.dirname(__filename))
console.log(path.join( base_dir, "resource", "output.png"));
var image_name = path.join( base_dir, "resource", "output.png")
var formData = { image1: fs.createReadStream(image_name) };
var json_body = "" ;
var obj_value= "";
return await new Promise(function(resolve,reject)
{
console.log("pls work",turnContext);
//\var turnContext1 = turnContext;
//\console.log(typeof(turnContext));
console.error('before post call...:1');
request.post({url:'http://127.0.0.1:5002/',formData: formData}, (err, httpResponse, body) =>
{
console.log("formdata....body....",formData);
console.log("inside request post");
if (err) {
reject(err);
}
else{
if (body != undefined) {
json_body = JSON.parse(body);
console.log("response inside", json_body);
resolve([json_body,turnContext]); //here we are not able to get the turncontext
} else {
reject('body undefined');
}
}
});
});
}
async flask_api(turnContext) {
var result = await this.initPromise(turnContext);
console.log("result", result);
console.log("result1", result[0]);
console.log("result2", result[1]);
}

var function calling for unknown reason

I have the code below, and it seems to call the var promiseFeedback is called and I don't know why... This means it is called even when an error occurs when I create document. Whereas is should only be called if there is no err in the createDocument.
Is anyone able to clear up why?
if (json) {
createDocument(documentUrl, context, json, function(res){
var promiseFeedback = callFB (context, res);
var collection = `mydb`
client.createDocument(collection, res, (err, result) => {
if(err) {
context.log(err);
return context.done();
} else {
Promise.all([promiseFeedback]).then(function(results){
context.log("promiseFeedback: " + results[0]);
context.done();
});
}
});
});
}
function callFB(context, res) {
return new Promise((resolve, reject) => {
var requestUrl = url.parse( URL );
var requestBody = {
"id": res.id
};
var body = JSON.stringify( requestBody );
const requestOptions = {
hostname: requestUrl.hostname,
path: requestUrl.path,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(body),
}
};
var request = https.request(requestOptions, function(res) {
var data ="";
res.on('data', function (chunk) {
data += chunk
});
res.on('end', function () {
resolve(true);
})
}).on('error', function(error) {
context.log("request error:", error);
resolve(false);
});
request.write(body);
request.end();
});
}
var promiseFeedback = callFB (context, res);
This statement executes callFB immediately, not just assigns another name to the promise. This promise callFB is out of the callback(scope) of err and Promise.all([promiseFeedback]), it runs no matter what the result of client.createDocument is.
To fix this:
Remove var promiseFeedback = callFB (context, res); and change Promise.all([promiseFeedback]) to callFB(context, res). You don't need to use Promise.all as you only have one promise to resolve.
Or you can just move var promiseFeedback = callFB (context, res); into else segment.

Promises then/catch

I have the following code:
return requestAsync({
method: 'GET',
url: 'https://' + servers[num - 1] + ':8033/version.txt'
}).then().catch()
I tried throwing an error in the then handler but that didn't work
If a condition is not met in the then handler, I want throw an error that the catch handler handles. How can I get that done?
Code:
var P = require('bluebird');
var defer = function () {
var resolve, reject;
var promise = new P(function () {
resolve = arguments[0];
reject = arguments[1];
});
return {
resolve: function () {
resolve.apply(null, arguments);
return promise;
},
reject: function () {
reject.apply(null, arguments);
return promise;
},
promise: promise
};
};
var pool = {maxSockets: Infinity};
var requestAsync = function (options) {
options.pool = pool;
options.timeout = 60000;
options.rejectUnauthorized = false;
options.strictSSL = false;
var deferred = defer();
var r = request(options, function (err, res, body) {
if (err) {
return deferred.reject(err);
}
deferred.resolve(res, body);
});
deferred.promise.req = r;
return deferred.promise;
};
return requestAsync({
method: 'GET',
url: 'https://' + servers[num - 1] + ':8033/version.txt'
}).then(function (response) {
throw new Error('Server is not taken');
}).catch(function (err) { });
You can manually throw the error:
requestAsync({
method: 'GET',
url: 'https://' + servers[num - 1] + ':8033/version.txt'
})
.then(function () {
throw new Error("Catch me")
}))
.catch(function (error) {
console.error(error)
})
jsbin: https://jsbin.com/dewiqafaca/edit?html,js,console,output
Just use throw to generate a standard JavaScript exception in your then function and it should invoke the function in your catch block with whatever value you provide as the argument.

how to get readStream with thunk in koa ?

I want to pipe a request in a koa controller, It's work:
var s = require('through2')();
var req = http.request(url, function(res) {
res.pipe(s);
})
req.end(null);
s.on('close', function() {
console.log('has close');
});
this.body = s;
But with thunk , it seems to be not work.
var s = stream();
yield thunk(url, s);
this.body = s;
Here is the thunk:
var thunk = function (url, s) {
return function(callback) {
var req = http.request(url, function(res) {
res.pipe(s);
});
s.on('close', function() {
callback(null, null);
console.log('req inner close');
});
req.end(null);
}
}
Use a promise for this (return a promise, not a thunk). Off the top of my head, so you may need to play around with it:
function run(url, s) {
return new Promise(function(resolve, reject) {
var req = http.request(url, function(res) {
res.pipe(s);
res.on('end', function() {
req.end();
});
});
req.on('error', function(err) {
return reject(err);
});
s.on('close', function() {
console.log('req inner close');
return resolve();
});
});
}
Then:
yield run(url, s);

Resources