I have been trying to fetch data from XMLRPC client - javascript

This is a piece of code I wrote. I have trouble accessing data from Promise for later purposes.
function forgotPassword(params) {
return new Promise(function (resolve, reject) {
return client.methodCall('forgotPassword', params, function (error, value) {
if (error === null) {
if (value === true) {
console.log('Password Sent!!');
//subpy.kill('SIGINT');
return resolve('Password Sent!!');
}
else {
console.log('User Not Found!!');
//subpy.kill('SIGINT');
return resolve('User Not Found!!');
}
}
else {
console.log('Error while doing the Operation!!');
//subpy.kill('SIGINT');
return reject(error);
}
});
}
);
}

I suggest you read the docs on Async Functions and Promises.
In this case you can do a few things
new Promise(function (resolve, reject) {
return client.methodCall('forgotPassword', params, function (error, value) {
if (error === null) {
if (value === true) {
console.log('Password Sent!!');
//subpy.kill('SIGINT');
return resolve('Password Sent!!');
}
else {
console.log('User Not Found!!');
//subpy.kill('SIGINT');
return resolve('User Not Found!!');
}
}
else {
console.log('Error while doing the Operation!!');
//subpy.kill('SIGINT');
return reject(error);
}
});
})
.then(res => console.log(res))
.catch(rej => console.log(rej));
The then will be called if the resolve is called.
The catch will be called if there is an error or reject is called.
Another way is to use await inside a async function to wait until you get a result from the promise object
function myPromiseFunction(){
return new Promise(function (resolve, reject) {.....
}
async function myfunction() {
try {
var res = await myPromiseFunction(); // waits until result from promise
console.log(res);
} catch (error){
console.log(error);
}
}
myfunction();

Related

How to handle reject promise error in outer try catch with inner Promise.all?

When an error/rejection occurs in detectingDog or detectingDog, the error is successfully handled by the .catch(error of the Promise.all() but I want the error to be directly handled by the catch (err) of the try structure.
How can I do this ?
PS: I have already tried to get rid of the .catch(error but then the Promise.all() hangs forever
try {
function detectingDog(bufferedData) {
return new Promise((resolve, reject) => {
package.detectDog(bufferedData, function(error, data) {
if (error) {
reject(error);
} else {
return resolve(data);
}
});
});
}
function detectingCat(bufferedData) {
return new Promise((resolve, reject) => {
package.detectCat(bufferedData, function(error, data) {
if (error) {
reject(error);
} else {
return resolve(data);
}
});
});
}
Promise.all([
detectingDog(param1),
detectingCat(param2)
]).then(responseData => {
callback(undefined, responseData);
}).catch(error => {
// (1) I need to pass the error to the outer structure where error handling is done
});
} catch (err) {
console.log(err);
// handing of the inner error (2) here
callback(err);
}
Thanks!
...but I want the error to be directly handled by the catch (err) of the try structure.
You can't do that in a non-async function, because control has already left the try/catch by the time that rejection occurs, which is after whatever function this code is in (if any) has returned.
In an async function, you can use await on a promise, which will make a rejection throw, so it would go to your try/catch. So you could do the following, but keep reading because it's fairly odd:
// In an `async` function
try {
function detectingDog(bufferedData) {
return new Promise((resolve, reject) => {
package.detectDog(bufferedData, function(error, data) {
if (error) {
reject(error);
} else {
return resolve(data);
}
});
});
}
function detectingCat(bufferedData) {
return new Promise((resolve, reject) => {
package.detectCat(bufferedData, function(error, data) {
if (error) {
reject(error);
} else {
return resolve(data);
}
});
});
}
const responseData = await Promise.all([
detectingDog(param1),
detectingCat(param2)
]);
callback(responseData);
} catch (err) {
console.log(err);
callback(err);
}
...but it doesn't make a lot of sense to go to the trouble of converting callback APIs to promises if you're just going to provide a callback-based API to your caller. Just return a promise. That makes the whole try/catch disappear:
// No need for these to be nested
function detectingDog(bufferedData) {
return new Promise((resolve, reject) => {
package.detectDog(bufferedData, function(error, data) {
if (error) {
reject(error);
} else {
resolve(data); // No need for `return`
}
});
});
}
function detectingCat(bufferedData) {
return new Promise((resolve, reject) => {
package.detectCat(bufferedData, function(error, data) {
if (error) {
reject(error);
} else {
resolve(data);
}
});
});
}
function example(param1, param2) {
return Promise.all([
detectingDog(param1),
detectingCat(param2)
]);
}
You have two options here.
If you really need the try/catch block you will need to run your code in an async function, leveraging the fact that awaiting a rejected Promise will throw an error in this context:
(async function () { // you might not need the immediately invoking function wrapper depending on your context
try {
function one(bufferedData) {
// return a promise
}
function two(bufferedData) {
// return a Promise
}
const responseData = await Promise.all([
one(param1),
two(param2)
])
callback(undefined, responseData)
} catch (err) {
console.log(err);
// handing of the inner error (2) here
callback(err)
}
})()
Alternatively, you can also just handle the error in the catch block of your Promise chain:
function one(bufferedData) {
// return a promise
}
function two(bufferedData) {
// return a Promise
}
Promise.all([
one(param1),
two(param2)
])
.then((responseData) => {
callback(undefined, responseData)
})
.catch((err) => {
console.log(err);
// handing of the inner error (2) here
callback(err)
})

While call rest api in Javascript (NodeJS) and return response Undefined

When i call rest API and return response it show undefined but i console.log this response it return
var request = require("request");
function initialize() {
// Setting URL and headers for request
var options = {
url: 'http://postalpincode.in/api/pincode/400605',
json: true
};
// Return new promise
return new Promise(function (resolve, reject) {
// Do async job
request.get(options, function (err, resp, body) {
if (err) {
reject(err);
} else {
resolve(JSON.stringify(body));
}
})
})
}
function main() {
var initializePromise = initialize();
initializePromise.then(function (result) {
return result;
})
}
console.log('', main())
But when i console log this response it show output correct
var request = require("request");
function initialize() {
// Setting URL and headers for request
var options = {
url: 'http://postalpincode.in/api/pincode/400605',
json: true
};
// Return new promise
return new Promise(function (resolve, reject) {
// Do async job
request.get(options, function (err, resp, body) {
if (err) {
reject(err);
} else {
resolve(JSON.stringify(body));
}
})
})
}
function main() {
var initializePromise = initialize();
initializePromise.then(function (result) {
console.log('', result)
})
}
console.log('', main())
I want When i call rest API and return response it show correct output
The return inside the thenscope is not returning for the function main, but only for the thenscope of the promise. You need to return the promise like so:
function main() {
var initializePromise = initialize();
return initializePromise.then(function (result) {
return result;
})
}
main().then((result) => console.log('',result));
you can't make a sync function call an async method and expect to have get its result.
use async/await
async function main() {
var initializePromise = await initialize();
console.log(initializePromise)
}
My question is, why are you wrapping in a new Promise something that's already from a return type of Promise?
You could just do:
request.get(endpoint, options).then((response) => console.log(response)).catch((error) => console.log(error));
Let me know what's the output in that case.
The then resolution of initializePromise method resolves at a later stage when a response is fetched from REST HTTP call i.e. it does not get returned when you call main() method due to the fact it is async. To handle such code, you should either use a callback
function main(completionHandler) {
var initializePromise = initialize();
initializePromise.then(function (result) {
completionHandler(result);
})
}
main((result) => { console.log(result)})
or a promise
function main() {
// Return new promise
return new Promise(resolve => {
var initializePromise = initialize();
initializePromise.then(function (result) {
resolve(result);
})
}
}
main().then(result => console.log(result));
return new Promise(function (resolve, reject) {
// Do async job
request.get(options, function (err, resp, body) {
if (err) {
reject(err);
} else {
try {
resolve(JSON.stringify(body));
} catch(e) {
reject(e);
}
}
})
})
in main function:
function main() {
initialize().then((result) => {
console.log(result);
return result;
}).catch((err) => {
console.log(err);
return err;
})
}

unable to resolve inner promise in javascript

Unable to resolve or come out of inner promise so I can send the data back to client side.
Code:
function getAmazonData(url, isRatings) {
var parsedData;
var ItemLookup;
var ratingsURL;
return new Promise(function (resolve, reject) {
request(url, function (err, response, body) {
if (err) return reject(err);
parseXML(body, function (err, parsedData) {
if (err) return reject(err);
ItemLookup = parsedData['ItemLookupResponse'];
if (ItemLookup && ItemLookup.Items && ItemLookup.Items.length > 0) {
// Request Error
if (ItemLookup.Items[0].Request && ItemLookup.Items[0].Request.length > 0 && ItemLookup.Items[0].Request[0].Errors) {
return reject(ItemLookup.Items[0].Request[0].Errors);
} else if (ItemLookup.Items[0].Item) {
ratingsURL = ItemLookup.Items[0].Item[0].CustomerReviews[0].IFrameURL[0];
if (isRatings) {
console.log('getting ratings...');
return new Promise(function (resolve2, reject2) {
request(ratingsURL, { json: true }, function (ratingsError, ratingBody) {
if (ratingsError) {
return reject2('Error in getting ratings');
}
ItemLookup.Items[0].Item[0].CustomerReviews.push({ Ratings: ratingBody });
resolve2(ItemLookup.Items[0].Item[0].CustomerReviews);
});
});
}
console.log('Resolved: ', ItemLookup.Items[0].Item);
resolve(ItemLookup.Items[0].Item);
}
}
});
});
});
}
amazon_router.get('/getDetails', function (req, res, next) {
var amazonApi = decodeURIComponent(req.query.url);
var amzonApiUrl = amazonApi.replace(/\+/g, '%2B');
var isRatings = decodeURIComponent(req.query.ratings);
console.log('');
console.log('amazon api url ', amzonApiUrl);
console.log('');
getAmazonData(amzonApiUrl, isRatings).then(function (err, response) {
if (err) res.send(err);
res.send(response);
});
});
The data is never sent after resolving promise here at LINE 10: res.send(response); There's something wrong with inner promise but I am not sure not do I fix it?
It looks like you are mixing callbacks and Promises. I would recommend wrapping all calls to Promises.
From the looks of it you don't need inner Promise because request expects a callback so you can easily resolve the outer one.
You also have some branches of if statements that don't call resolve or reject (marked in the code bellow with comments). You have to call resolve/reject in all branches otherwise the Promise 'might do nothing' in case it hits the branch.
function getAmazonData(url, isRatings) {
var parsedData;
var ItemLookup;
var ratingsURL;
return new Promise(function (resolve, reject) {
request(url, function (err, response, body) {
if (err) return reject(err);
parseXML(body, function (err, parsedData) {
if (err) return reject(err);
ItemLookup = parsedData['ItemLookupResponse'];
if (ItemLookup && ItemLookup.Items && ItemLookup.Items.length > 0) {
// Request Error
if (ItemLookup.Items[0].Request && ItemLookup.Items[0].Request.length > 0 && ItemLookup.Items[0].Request[0].Errors) {
reject(ItemLookup.Items[0].Request[0].Errors);
} else if (ItemLookup.Items[0].Item) {
ratingsURL = ItemLookup.Items[0].Item[0].CustomerReviews[0].IFrameURL[0];
if (isRatings) {
console.log('getting ratings...');
request(ratingsURL, { json: true }, function (ratingsError, ratingBody) {
if (ratingsError) {
reject(new Error('Error in getting ratings'));
return;
}
ItemLookup.Items[0].Item[0].CustomerReviews.push({ Ratings: ratingBody });
resolve(ItemLookup.Items[0].Item[0].CustomerReviews);
});
} else {
console.log('Resolved: ', ItemLookup.Items[0].Item);
resolve(ItemLookup.Items[0].Item);
}
} else {
// resolve or reject here
}
} else {
// resolve or reject here
}
});
});
});
}
Wrapping call to Promise:
function requestAsPromised(url) {
return new Promise(function (resolve, reject) {
request(url, function (err, response, body) {
if (err) {
reject(err);
} else {
resolve(body)
}
});
})
}
You need to use return to return the inner promise(s),
function getAmazonData(url, isRatings) {
var parsedData;
var ItemLookup;
var ratingsURL;
return new Promise(function (resolve, reject) {
return request(url, function (err, response, body) {
if (err) return reject(err);
return parseXML(body, function (err, parsedData) {
if (err) return reject(err);
ItemLookup = parsedData['ItemLookupResponse'];
if (ItemLookup && ItemLookup.Items && ItemLookup.Items.length > 0) {
// Request Error
if (ItemLookup.Items[0].Request && ItemLookup.Items[0].Request.length > 0 && ItemLookup.Items[0].Request[0].Errors) {
return reject(ItemLookup.Items[0].Request[0].Errors);
} else if (ItemLookup.Items[0].Item) {
ratingsURL = ItemLookup.Items[0].Item[0].CustomerReviews[0].IFrameURL[0];
if (isRatings) {
console.log('getting ratings...');
return new Promise(function (resolve2, reject2) {
request(ratingsURL, { json: true }, function (ratingsError, ratingBody) {
if (ratingsError) {
return reject2('Error in getting ratings');
}
ItemLookup.Items[0].Item[0].CustomerReviews.push({ Ratings: ratingBody });
resolve2(ItemLookup.Items[0].Item[0].CustomerReviews);
});
});
}
console.log('Resolved: ', ItemLookup.Items[0].Item);
return resolve(ItemLookup.Items[0].Item);
}
}
});
});
});
}
Since it looks like Node.js code, try using async/await

Bluebird<void> is not assignable to Bluebird<ProcessInstance> in return statment

I'm trying to return a promise with an .try(function(){}).catch(function(){}) block. My problem is caused by the type of my promise.
deleteProcess(processId: number): Promise<ProcessInstance> {
let deletedProcess = this.Process.findById(processId);
return Promise
.try(function () {
this.Process.destroy({
where: {
processId: processId
}
})
.then(function (rowDeleted) {
if (rowDeleted === 1) {
console.log('Deleted successfully');
return this.getDeletedProcess();
}
})
.catch(function (err) {
console.log(err);
})
});
function getDeletedProcess(): ProcessInstance {
return this.deletedProcess;
};
};
The error says, that type 'Bluebird void' is not assignable to type 'Bluebird ProcessInstance'
This post was really helpful to solve the problem
Bluebird.JS Promise: new Promise(function (resolve, reject){}) vs Promise.try(function(){})
This solves the problem:
return new Promise<ProcessInstance>(
(function (resolve, reject) {
this.Process.destroy({
where: {
processId: processId
}
})
.then(function (rowDeleted) {
if (rowDeleted === 1) {
console.log('Deleted successfully');
return this.getDeletedProcess();
}
})
reject(function (err) {
console.log(err);
})
})
)

NodeJs get result from previous chain as async and pass it to nested function

after uploading image from client as Base64 to server i want to
save file to disk
get result of save (first chain) and pass it to next chain
check result on next function on that(), if its true, update database and return result
check result and print
this below code is my implementing chain, but that seems is not correct, because i cant get result from first chain as savePhotoOnDisk
savePhotoOnDisk(filenameWithPath)
.then(updateUserPhoto(result, userId, filename))
.then(FUNCTION(GET RESULT)
.then(OTHER FUNCTION() {
PRINT RESULT
});
or this chain:
savePhotoOnDisk(filenameWithPath)
.then(function(result){
updateUserPhoto(result, userId, filename);
})
.then(function (result) {
OTHER FUNCTION
})
.then(function (result) {
PRINT RESULT
})
.catch(function (v) {
log.info('error chaining');
});
function updateUserPhoto(result, userId, filename) {
log.info(result);
return new Promise(function (resolve, reject) {
var query = "UPDATE users SET userPhoto = ? WHERE userId = ? ;";
connection.query(query, [filename, userId], function (err, results) {
if (err) return reject(false);
if (results.length === 0) return reject(false);
resolve(true);
});
});
}
function savePhotoOnDisk(filename) {
return new Promise(function (resolve, reject) {
require("fs").writeFile(filename, base64Data, 'base64', function (err) {
log.info(err + "upload");
if (err == null)
resolve(true);
else
reject(false);
});
});
}
I'm newbie to use this nodejs feature, please help to fix that, Thanks
UPDATE
savePhotoOnDisk(filenameWithPath)
.then(function (result) {
return {success:result};
})
.then(updateUserPhoto(success, userId, filename),function (result) {
console.log(result);
})
.catch(function (v) {
log.info('error chaining');
});
You are calling promise inside promise which is the issue. Try changing the code to something like this.
savePhotoOnDisk(filenameWithPath)
.then(function () {
return {
userId : userId,
fileName : fileName
}
})
.then(updateUserPhoto)
.then(FUNCTION(GET RESULT)
.then(OTHER FUNCTION() {
PRINT RESULT
});
function updateUserPhoto(data) {
var userId = data.userId;
var fileName = data.fileName;
// call your function as it was earlier.
}
EDIT
savePhotoOnDisk(filenameWithPath)
.then(updateUserPhoto.bind(true, userId, filename))
.then(function (result) {
OTHER FUNCTION
})
.then(function (result) {
PRINT RESULT
})
.catch(function (v) {
log.info('error chaining');
});
function updateUserPhoto(result, userId, filename) {
log.info(result);
return new Promise(function (resolve, reject) {
var query = "UPDATE users SET userPhoto = ? WHERE userId = ? ;";
connection.query(query, [filename, userId], function (err, results) {
if (err) return reject(false);
if (results.length === 0) return reject(false);
resolve(true);
});
});
}
function savePhotoOnDisk(filename) {
return new Promise(function (resolve, reject) {
require("fs").writeFile(filename, base64Data, 'base64', function (err) {
log.info(err + "upload");
if (err == null)
resolve(true);
else
reject(false);
});
});
}
Problem Resolved
this is my correct code to create simple chain and pass result to next method as Promise
I hope to helpful this post
savePhotoOnDisk(filenameWithPath, photoBase64).then(function (result) {
return updateUserPhoto(result, userId, filename);
}).then(function (save) {
if (save)
socket.emit('uploadUserPhoto', true);
else
socket.emit('uploadUserPhoto', false);
}).catch(function (v) {
socket.emit('uploadUserPhoto', false);
});

Categories