Can I make synchronous call with `request` npm package? - javascript

I am using request module in my NodeJS application, for making server-to-server API calls. I am making the API call like this:
request(options, function (error, response, body) {
if( error ){
// return error response
}
// return success response here
});
For some reason, I need to not use this asynchronous way of making call, but do it synchronously. So, is there any way to make this call in synchronous manner. I tried and found some other modules for this, but I need to use this same module.
Thanks

No you cannot not. Request will return you promise and you have to handle it somewhere using .then() or calling the function with async/await pattern.

Because an HTTP request is asynchronous by nature, you cannot do it synchronously. However, you can use ES6+ Promises and async/await like so:
// First, encapsulate into a Promise
const doRequest = () => new Promise((resolve, reject) => request(options, function (error, response, body) {
if( error ){
reject(error)
}
resolve(response)
});
// And then, use async/await
const x = 1 + 1
const response = await myRequest()
console.log(response)
More info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

As indicated by #Errorname, promises are probably what you are looking for. Instead of writing the code by hand, you could also use the package request-promise: https://www.npmjs.com/package/request-promise

If you want a strongly-typed, synchronous client, you can try out ts-sync-request.
NPM: https://www.npmjs.com/package/ts-sync-request
This library is a wrapper around sync-request.
You can attach a header & make a request like below:
import { SyncRequestClient } from 'ts-sync-request/dist'
let url = "http://someurl.com";
let response = new SyncRequestClient()
.addHeader("content-type", "application/x-www-form-urlencoded")
.post<string, MyResponseModel>(url, "city=Dubai");

Related

How to get return value from stub function?

Using grpc, i create a stub 'client'.
He has an 'auth' method.
I call like that
client.auth({uuid:cookies.uuid}, function(err, r){} );
The function in the parameter will be called asynchronously, but I need to get its value synchronously.
How can this be done?
Is impossible to convert an asynchronous method to a synchronous one. You can "simulate" it vanilla with async/await and promises, without any external package.
function clientLogin() {
return new Promise((accept, reject) => {
client.auth({uuid:cookies.uuid}, (err, r){
if (err) {
reject(err);
} else {
accept(r);
}
});
});
}
// This code needs to run inside and async function
try {
let r = await clientLogin();
console.log(r);
} catch (e) {
console.error(e);
}
clientLogin() returns a Promise that will be resolved later in the future (AKA asynchronous). With the await keyword you can tell JavaScript to wait for the Promise to resolve before continuing with the execution, so is a simulated synchronous code, although is not really syncrhonous.
If you are not used to async/await, is a bit long to explain, so better look for a tutorial.
That is an asynchronous operation. You can't make it complete synchronously. You could use a library like grpc-promise or grpc-caller to get a promise, and then use await to be able to code in a similar style to synchronous code.

Promises and Meteor.call()

I have a Meteor.method() that server side returns a promise from oracledb. Client side I have:
Meteor.call('myMethod', (error, result) => {
result.then() // err -> no .then() method?,
});
So what is result? It does not have a .then() method, so it is not a promise?
Meteor does not "send" the promise to the client.
The server returns a result value to the client (which triggers the callback) once the promise is resolved (or rejected) on the server, and not at the moment the promise is returned from the method itself (unless it is already settled when returned).
You can also use async/await to simplify the code.
Here is a blog post with more details about the using asynchronous code in methods.
Note:
The value sent from the server is serialized using EJSON. Object methods, getters, etc. are stripped from it, unless you create a custom serializer. In some cases, serialization might even fail (I think it happened with certain moment objects) and result in undefined being returned.
Meteor is not using promises by default, however, you can wrap your Meteor.calls into a promise function as below
const callWithPromise = (method, myParameters) => {
return new Promise((resolve, reject) => {
Meteor.call(method, myParameters, (err, res) => {
if (err) reject('Something went wrong');
resolve(res);
});
});
}
(async function() {
const myValue1 = await callWithPromise('myMethod1', someParameters);
const myValue2 = await callWithPromise('myMethod2', myValue1);
})();
Sample code has copied from Meteor forum.
Also, this topic gives you a better insight in taking advantages of Aysnc/Await syntax or Promises in Meteor calls.

NodeJS wait for HTTP request

I want to write an application that requests a token from an API. As long as this token isn't available I don't want to continue with the rest of the application. So it has to be like a synchronous HTTP request.
My goal is to create a function that does the request and then returns the token like:
var token=getToken(); //After this function has finished
makeRequest(token); //I want this function to be executed
How can I do this?
It doesn't want to be synchronous at all. Embrace the power of callbacks:
function getToken(callback) {
//get the token here
callback(token);
};
getToken(function(token){
makeRequest(token);
});
That ensures makeRequest isn't executed until after getToken is completed.
My goal is to create a function that does the request and then returns the token
You cannot make a function that returns a value that it doesn't have immediately. You can only return a promise.
Then in some other part of code you can either wait for the promise to be fulfilled by using the then handler, or you can use something like:
var token = await getToken();
inside of an async function to wait for that value to be available, but only if the getToken() function returns a promise.
For example, using the request-promise module it would be something like:
var rp = require('request-promise');
function getToken() {
// this returns a promise:
return rp('http://www.example.com/some/path');
})
And then some other function:
function otherFunction() {
getToken().then(token => {
// you have your token here
}).catch(err => {
// you have some error
});
}
Or, with async function something like this:
async function someFunction() {
try {
var token = await getToken();
// you have your token here
} catch (err) {
// you have some error
}
}
See: https://www.npmjs.com/package/request-promise
Note that async function and await is define in ECMAScript 2017 Draft (ECMA-262) which is not final yet at the time of this writing as of March 2017 (it will be in June 2017).
But it's already available in Node since v7.6 (and it was available since v7.0 if you used the --harmony flag). For the compatibility with Node versions, see:
http://node.green/#ES2017-features-async-functions
If you want similar features for older Node versions with slightly different syntax, you can use modules like co or Promise.coroutine from Bluebird.
You can use javascript Promise or promise library like async
By javaScript promise:
new Promise((resolve, reject) => {
resolve(getToken());
}).then(token =>{
//do you rest of the work
makeRequest(token);
}).catch(err =>{
console.error(err)
})
You can use the feature of ES6 called generator. You may follow this article for deeper concepts. But basically you can use generators and promises to get this job done. I'm using bluebird to promisify and manage the generator.
Your code should be fine like the example below.
const Promise = require('bluebird');
function getToken(){
return new Promise(resolve=>{
//Do request do get the token, then call resolve(token).
})
}
function makeRequest(token){
return new Promise(resolve=>{
//Do request do get whatever you whant passing the token, then call resolve(result).
})
}
function* doAsyncLikeSync(){
const token= yield getToken(); //After this function has finished
const result = yield makeRequest(token); //I want this function to be executed
return result;
}
Promise.coroutine(doAsyncLikeSync)()
.then(result => {
//Do something with the result
})

node 7.6 async await issues with returning data

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.

Node Request Library - Promise Refactoring

I am using the Node request library which can be found at the following link
https://github.com/request/request
I have a number of functions which look like the following
function doRequest() {
return new Promise(function(resolve,reject) {
request('some-url', function(error,response,body) {
if (!error && response.statusCode === 200) {
resolve(body)
}
});
});
}
I then call these functions like so
doRequest()
.then(function(response){
console.log(response);
})
My question is, is there a way of writing my doRequest function without having to create a new Promise? I feel like it is awkward looking and could possibly be an anti-pattern? Sort of how in AngularJS you often see people using
$q.defer()
when making http calls, when the http call already returns a promise.
Any advice would be great.
If you wanted to make Promises manually based on the results of the request() method then that is the right way to do it (although a reject() call on error is also required).
However that request library already appears to support the Bluebird Promise library's Promisify function, which can automatically wrap those functions into ones that return Promises.

Categories