synchronous function call in node js - javascript

I am trying to make synchronous call to functions in my node js code.
I am calling my functions like this
set_authentication();
set_file();
function set_authentication(){
---
callback function
---
}
I want that my set_authentication() function should execute first completely and then set_file() should start execution but set_file() function start executing before the callback of set_authentication().
I have tried this using async also like
async.series(
[
// Here we need to call next so that async can execute the next function.
// if an error (first parameter is not null) is passed to next, it will directly go to the final callback
function (next) {
set_looker_authentication_token();
},
// runs this only if taskFirst finished without an error
function (next) {
set_view_measure_file();
}
],
function(error, result){
}
);
but it also doesn't work.
I tried promise also
set_authentication().then(set_file(),console.error);
function set_authentication(){
---
callback function
var myFirstPromise = new Promise((resolve, reject) => {
setTimeout(function(){
resolve("Success!");
}, 250);
});
---
}
here I am getting this error:- Cannot read property 'then' of undefined.
I am new to node and js.

You need to return Promise, because you call .then method of a returned promise:
set_authentication().then(set_file);
function set_authentication() {
return new Promise(resolve => { // <------ This is a thing
setTimeout(function(){
console.log('set_authentication() called');
resolve("Success!");
}, 250);
});
}
function set_file(param) {
console.log('set_file called');
console.log(
'received from set_authentication():', param);
}

If set_authentication is async func, you need to pass set_file as callback to set_authentication function.
You may also consider to use promises as you wrote, but you need to implement it before you start chaining.

use async.auto like this:
async.auto(
{
first: function (cb, results) {
var status=true;
cb(null, status)
},
second: ['first', function (results, cb) {
var status = results.first;
console.log("result of first function",status)
}],
},
function (err, allResult) {
console.log("result of executing all function",allResult)
}
);

Related

Method does not wait for Promise to be resolved

I have a function that I'm trying to call and basically force it to wait for a response before continuing onto the next thing.
I have two functions, both are asynchronous.
The first one looks something like this, with all parameters that begin with an '_' to be used as callbacks:
async function formatJson(input, _sendToThirdParty, _handleLogs, _setDimensions)
{
...do some work here to format the payload
if(onlineConnectionRequired)
{
_setDimensions(itemToUpdate, object);
}
else {
// Do non-online based transformations here
}
...do more work after the above
}
Basically from that, I'm trying to call this method setDimensions which looks like this:
async function setDimensions(itemToUpdate, object) {
try
{
if(itemToUpdate != null)
{
console.log("Loading dimensions");
await Promise.resolve(function() {
ns.get(`inventoryItem/${object['Item ID']}?expandSubResources=true`)
.then((res) => {
console.log("Inventory Item Loaded. Updating dimensions...");
itemToUpdate.consignments.push(
{
consignmentID: object.conID,
barcode: object.barcode,
itemID: '', // leaving as empty for now
width : res.data.custitem_width,
length : res.data.custitem_length,
height : res.data.custitem_height,
weight : res.data.custitem_weight,
fragile: object.fragile === 'T' ? 1 : 0,
description: object.description
}
);
console.log("Dimensions Finalised");
})
});
}
}
catch(err)
{
console.log(err);
const message = `Error attempting to set the dimensions for ${object['Item ID']}`;
console.log(message);
throw new Error(message);
}
}
The problems I'm coming across are:
The code from the first method continues on before waiting for the promise to resolve, but I need it to wait so I can fully finish building up the payload before it continues on doing the next bits
If I try and include the await keyword before my call to _setDimensions(...) in the first method, I get an error "SyntaxError: await is only valid in async function", but I would've thought that it was an async function?
If anyone could help, that would be incredibly appreciated! Thank you!!
The correct design of your functions are below:
formatJson(input, (err, value) => {
if(err) {
// Error handler goes here
//console.log(err);
throw err;
} else {
// Implementation for working with returned value
console.log(value);
}
});
function formatJson(input, callback)
{
//...do some work here to format the payload
if(onlineConnectionRequired)
{
setDimensions(itemToUpdate, object)
.then((updatedItem) => {
// Implement anything here to work with your
// result coming from setDimensions() function
//console.log(updatedItem);
// Callback with null error and updatedItem as value
callback(null, updatedItem);
})
.catch((err) => {
// Callback with err object and null value
callback(err, null);
});
}
else {
// Do non-online based transformations here
}
//...do more work after the above
}
function setDimensions(itemToUpdate, object) {
try
{
if(inventoryItemID != null)
{
console.log("Loading dimensions");
return new Promise(function(resolve, reject) {
ns.get(`inventoryItem/${object['Item ID']}?expandSubResources=true`)
.then((res) => {
console.log("Inventory Item Loaded. Updating dimensions...");
itemToUpdate.consignments.push(
{
consignmentID: object.conID,
barcode: object.barcode,
itemID: '', // leaving as empty for now
width : res.data.custitem_width,
length : res.data.custitem_length,
height : res.data.custitem_height,
weight : res.data.custitem_weight,
fragile: object.fragile === 'T' ? 1 : 0,
description: object.description
}
);
console.log("Dimensions Finalised");
resolve(itemToUpdate);
})
.catch((err) => reject(err));
});
}
}
catch(err)
{
console.log(err);
const message = `Error attempting to set the dimensions for ${object['Item ID']}`;
console.log(message);
throw new Error(message);
}
}
Mistakes in your code:
Your formatJson function had async keyword but your formatJson function had callback functions named _sendToThirdParty, _handleLogs, _setDimensions. There are 3 types of implementation to create asynchronous codes. You can use callbacks, Promises or async/await. But Promises and async/await are the same except their uses cases and syntaxses. When you define a function as async fn() {...} it basically return a new Promise, so it is equal saying fn() { return new Promise(); }. Functions with callbacks have a shape like function(params, callback) { callback(cbParams); } you can use call callback function in a several branches in your function. But you only have single callback function, your code had 3 callback functions. Also note that functions with callback don't have async keyword. This is not valid because as I mentioned earlier, an async function will return a Promise. So you should not (but you can) define a function as async function(params, callback) like you did in your first method. This is definition is not wrong and it can work but it's not valid.
Your second method was an async function which was returning nothing. So I have changed it to normal function with returning a Promise.
Is the formatJson method beeing called inside an async method? It need to be, and before _setDimensions you need to add a await keyword.
And, as Daniel said, use the promise constructor.

JS - how to hook into success and error callbacks from a different file

I have my JS set up as follows.
App1.js
function x(){
thirdPartyLibrary.performAsyncTask((resultObject, errorObject) => {
// This is a callback function, invoked when performAsyncTask is done.
// I can handle resultObject and errorObject here.
});
}
Let's say I have other files as part of this app. Each of them calls x(), and would invoke their own version of a handleSuccess() or handleError() function depending on the results of the call to x().
How can I structure the call to x() such that I can achieve this? It's almost like I want to "listen" to the results of performAsyncTask() from App1.js, but I'm not sure how to do that.
If you need to stay with callbacks (due to very old JS clients or whatever), you can provide the callback as parameter to x:
function x(myCallback) {
thirdPartyLibrary.performAsyncTask(myCallback);
}
// other file:
x((resultObject, errorObject) => {
// handle just like before
});
You could even change it to two callbacks, depending on the result. Only one of your callbacks will be called in the end:
function x(successCallback, errorCallback) {
thirdPartyLibrary.performAsyncTask((resultObject, errorObject) => {
if (errorObject) return errorCallback(errorObject);
else return successCallback(resultObject);
});
}
// other file:
x(
function handleSuccess(resultObject) {
// handle success
},
function handleError(errorObject) {
// handle error
}
);
Have x return a Promise that resolves with resultObject if there's no error, or rejects with errorObject if there is an error. Then, callers of x can chain .then onto the Promise to handle successes, and chain .catches to handle failures:
function x(){
return new Promise((resolve, reject) => {
thirdPartyLibrary.performAsyncTask((resultObject, errorObject) => {
if (errorObject) reject(errorObject);
else resolve(resultObject);
});
});
}
x()
.then(result => {
// handle successful result
})
.catch(err => {
// handle error
});

How to have one function wait for another function to finish processing in javascript using chaining?

I have a function that pulls an array from firebase via its rest api, which I need to input into another function to create a calendar.
function array_from_firebase(){
//code that pulls from firebase
return array
}
function calendar_create_from_array(array){
//code that generates calendar
}
The following does not work:
calendar_create_from_array(array_from_firebase())
However, this does work
array = array_from_firebase()
setTimeout(calendar_create_from_array,9000,array)
I believe this means that array_from_firebase takes a bit of time longer than calendar_create_from_array and calendar_create_from_array triggers too quickly.
How could I use chaining and promises to solve this?
From the first function you can return a promise. In this example usage of setTimeout is just to demonstrate that the next function execute after the first function
function array_from_firebase() {
return new Promise(
function(resolve) {
setTimeout(function() {
return resolve([1, 2, 3])
}, 4000)
},
function(reject) {})
}
function calendar_create_from_array(array) {
console.log(array);
}
array_from_firebase().then(function(resp) {
calendar_create_from_array(resp)
})
You can also use async & await.In this case the function which will wait for the result from another function need to be declared as async and declare await keyword before the function which will return the result.
function array_from_firebase() {
return new Promise(
function(resolve) {
setTimeout(function() {
return resolve([1, 2, 3])
}, 5000)
},
function(reject) {})
}
async function calendar_create_from_array() {
console.log('Calling function and waiting for result for 5secs....')
let getResult = await array_from_firebase();
console.log('Got result after 5secs', getResult)
}
calendar_create_from_array()
When you work with asynchronous code, you usually deal with Promises, which you have handle with .then and .catch blocks, to force you functions to wait for response. I've simulated the async call inside array_from_firebase function, it returns the response after 3 seconds, and the response is a Promise. Then you can handle this promise via .then block (as shown in calendar_create_from_array function), it will be executed, when you get the response with no errors, and .catch block will be executed when you get the error in response. Something like this:
function array_from_firebase() {
// Simulate async response
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve([1,2,3]);
}, 3000);
})
}
function calendar_create_from_array() {
array_from_firebase()
.then(function(response) {
console.log(response);
})
}
calendar_create_from_array();

Javascript and callbacks and defered. How can I run a function after a google gmail API request completes?

I have built up a javascript file that starts with:
var myApp = function () {
var CLIENT_ID = 'xxxxxxx';
var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest"];
var SCOPES = 'https://www.googleapis.com/auth/gmail.readonly https://www.googleapis.com/auth/analytics.readonly https://www.googleapis.com/auth/drive.readonly';
var authorizeButton = document.getElementById('authorize-button');
return {
The functions are declared like:
getSent: function(callback) {
var request = gapi.client.gmail.users.messages.list({
'userId': 'me',
'labelIds': 'SENT',
'maxResults': 10
});
request.execute(function(response) {
$.each(response.messages, function() {
var messageRequest = gapi.client.gmail.users.messages.get({
'userId': 'me',
'id': this.id
});
messageRequest.execute(myApp.appendMessageRow);
});
});
},
And then run through a single function that calls others:
myApp.init();
How can I defer a function to be run after my google request function getsent() has been fully completed. I have tried using callbacks to another function and it runs but it runs while the getsent() is still being executed. Can I use the jQuery method defered to run the callback when done?
I have tried:
myApp.getSent(myApp.gMailSyncComplete()); // Runs early
and I tried:
myApp.getSent().done(myApp.gMailSyncComplete()); // no jQuery done defined
Some important errors in your code:
You are creating a function getSent that accepts a callback, but you are not calling the callback at all so it won't get executed ever. You should execute the callback when everything else is done.
You are not waiting for all message requests to be completed. You can use a library like async which has the method map to be able to execute all requests in parallel and wait for all of them to be completed before calling the callback.
With these two things in mind, and using async, this would be an example of the resulting code:
getSent: function (callback) {
var request = gapi.client.gmail.users.messages.list({
'userId': 'me',
'labelIds': 'SENT',
'maxResults': 10
})
request.execute(function (response) {
async.map(response.messages, function (msg, cb) {
var messageRequest = gapi.client.gmail.users.messages.get({
'userId': 'me',
'id': msg.id
})
messageRequest.execute(function (result) {
myApp.appendMessageRow(result)
cb()
})
}, function (err) {
if (err) throw err
callback()
})
})
}
Lastly, when invoking this function, keep in mind that the callback parameter must be a function.
To make things clear, let's translate the code you wrote, myApp.getSent(myApp.gMailSyncComplete()), into an equivalent structure:
var callback = myApp.gMailSyncComplete()
myApp.getSent(callback)
When you do this, you are not passing the function but the result of the function, because you are executing it. That's why it gets executed immediately. The correct way to do this would be the following:
var callback = myApp.gMailSyncComplete
myApp.getSent(callback)
Or, in your one-liner example, myApp.getSent(myApp.gMailSyncComplete)
you can use javascript promise.
function testPromise() {
let p1 = new Promise(
// The resolver function is called with the ability to resolve or
// reject the promise
(resolve, reject) => {
/*your async function*/
}
);
// defined what to do when the promise is resolved with the then() call,
// and what to do when the promise is rejected with the catch() call
p1.then(
// Log the fulfillment value
function(val) {
log.insertAdjacentHTML('beforeend', val +
') Promise fulfilled (<small>Async code terminated</small>)<br/>');
})
.catch(
// Log the rejection reason
(reason) => {
console.log('Handle rejected promise ('+reason+') here.');
});
}
You could use jQuery promise(), check the example below.
getSent: function() {
var request = gapi.client.gmail.users.messages.list({
'userId': 'me',
'labelIds': 'SENT',
'maxResults': 10
});
request.execute(function(response) {
$.each(response.messages, function() {
var messageRequest = gapi.client.gmail.users.messages.get({
'userId': 'me',
'id': this.id
});
messageRequest.execute(myApp.appendMessageRow);
});
});
},
...
$.when( myApp.getSent() ).done(function() {
// do whatever you want in here as callback
});
Inside of your getSent function create a jQuery Deferred object and return a promise. Then after request.execute has finished you can call resolve/reject. I created a small snippet to show example. Maybe you can modify to fit your needs
$(document).ready(function () {
var i =0;
function getText() {
var deferred = $.Deferred();
setTimeout(function () {
i++;
deferred.resolve("text " + i);
}, 3000);
return deferred.promise();
}
getText().then(function (value) {
console.log(value);
}).then(function () {
getText().then(function (value2) {
console.log(value2);
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

How ensure async request has finished before running a function

I am performing an async request to pull data from a server and then call a function after the request. My question is how do I ensure the request is complete and all data loaded before processRecords() runs?
Thanks in advance.
function getRecords () {
var ids = Server.getIds();
var allTheRecords = [];
ids.forEach(function(recordId) {
Server.getRecord(recordId, function (error, data) {
if(error) {
console.log(error);
} else {
allTheRecords.push(data);
};
});
});
processRecords(allTheRecords);
}
How are you performing the Asynchronous request? If it's an AJAX request, the API provides for callbacks to be supplied based on the result of the call.
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
You could use the native Promise api to perform the async actions for you.
Using Promise.all you can give it an array of promises that need to be resolved before calling the processRecords function.
It also now more reusable as you have a getRecord function that you could use elsewhere in your code.
You should probably think of a way to add in the ability to get multiple records from the server if you control it though. You don't really want to fire off a bunch of network requests if you can do it in just one.
// Server mock of the api you have shown
const Server = {
getRecord(id, callback) {
console.log('getRecord', id)
callback(null, {id})
},
getIds() {
return [1, 2, 3]
}
}
function getRecords (ids, processRecords) {
console.log('getRecords', ids.join())
// mapping the array of id's will convert them to an
// array of Promises by calling getRecord with the id
Promise.all(ids.map(getRecord))
// then is called once all the promises are resolved
.then(processRecords)
// this will be called if the reject function of any
// promise is called
.catch(console.error.bind(console))
}
function getRecord(recordId) {
// this function returns a Promise that wraps your
// server call
return new Promise((resolve, reject) => {
Server.getRecord(recordId, function (error, data) {
if(error) {
reject(error)
} else {
resolve(data)
}
})
})
}
getRecords(Server.getIds(), function(records) {
console.log('resolved all promises')
console.log(records)
})

Categories