Stop or break promises - javascript

I am trying to check on an API if a picture It is valid. I am doing it with promises, I want that if a check on API return me a failure, stop execute de promise and call a fuction.
Heres my code.
My function to call the promises
checkPhotos(options,formData, "front", res, false).then(function(response) {
if(response!== 'error'){
options.url = 'http://'+config.verifier_host+':'+config.verifier_port+config.verifier_endpoint_sc;
readImage = fs.createReadStream("tmp/"+imgOne+".jpeg");
formData = {
uuid : request.uuid,
document_type : 1, //req.body.document_type
analysis_type : 1,
document_image: {
value: readImage,
options: {
filename: 'tmp/'+imgOne+'.jpeg',
contentType: null
}
}
};
console.log("2a Ejecución")
return checkPhotos(options,formData, "back", res, false);
}else {
return;
}
}).then(function(response) {
if(response!== 'error'){
options.url = 'http://'+config.verifier_host+':'+config.verifier_port+config.verifier_endpoint_sc;
readImage = fs.createReadStream("tmp/"+nombreImagenBackimg2+".jpeg");
formData = {
uuid : request.uuid,
document_type : 1, //req.body.document_type
analysis_type : 2,
document_image: {
value: readImage,
options: {
filename: 'tmp/'+img2+'.jpeg',
contentType: null
}
}
};
console.log("3a Ejecución")
return checkPhotos(options,formData, "back", res, false);
}else {
return;
}
}).then(function(response) {
if(response!== 'error'){
readImage = fs.createReadStream("tmp/"+nombreImagenSelfieimg3+".jpeg");
formData = {
uuid : request.uuid,
selfie_image: {
value: readImage,
options: {
filename: 'tmp/'+img3+'.jpeg',
contentType: null
}
}
};
options.url = 'http://'+config.verifier_host+':'+config.verifier_port+config.verifier_endpoint_tc;
console.log("4a y última ejecución")
return checkPhotos(options, formData, null, res, true, request);
}else {
return;
}
}).catch(function(err) {
logger.error('PID ' + process.pid + ' Error response' + err.message);
console.log("Catch -> "+ err.message);
});
My function promise.
function checkPhotos (options, formData, positionPhoto, res, bandera, request) {
var promise = new Promise(function (resolve, reject) {
var post_req = requests.post({headers: {Authorization : options.headers.authorization}, url:options.url, formData: formData}, function (err, httpResponse, body) {
if (err) {
logger.error(' PID ' + process.pid + err);
return console.error('Error:', err);
}
if(!body){
logger.error(' PID ' + process.pid + formData.document_image.options.filename);
return false;
}
responseBody = JSON.parse(body);
if(bandera){
if(responseBody.success === 'error'){
resolve(responseBody.success);
return getData(null, res, responseBody);
}else {
resolve(formData);
getData(null, res);
}
}else {
if(responseBody.success === 'error'){
logger.error(' PID ' + process.pid + responseBody);
resolve(responseBody.success);
return getData(null, res, responseBody);
}else {
resolve(formData);
console.log("Success")
}
}
});
});
return promise;
}

Call reject on error instead of resolve. This way the promise chain is immediately rejected and any subsequent calls to .then are not run.
If you want to stop the promise chain from inside a .then call, you can return a Promise.reject(…) value OR throw an error.
Example:
const promise = checkPhotos(...);
promise
.then(askApi)
.then((response) => { throw response.body; })
.then(willNotBeExecuted)
.catch(thisWillbeExecutedAfterThrow);
function checkPhotos (options, formData, positionPhoto, res, bandera, request) {
return (resolve, reject) => {
// … make request
if (!bandera) { reject(getData); }
};
}

Related

how to handle exception for promise in loop?

I am downloading files with zip folder, but it download the zip folder prior to add files in the zip folder object. If I remove them and catch block from call of "this. UrlToPromise ()" it works right, but when it faced reject from "this. UrlToPromise ()" it does not work correctly.
var zip = new JSZip();
zip = this.makezip(files, zip);
zip.generateAsync({ type: "blob" }).then(function (content) {
if (downloadName) {
console.log('zip download one', zip);
FileSaver.saveAs(content, downloadName + '.zip');
} else {
FileSaver.saveAs(content, 'All.zip');
}
});
async makezip(files, zip, folderName = null) {
if (folderName)
var tempFolder = zip.folder(folderName);
for (var i in files) {
files[i].hasOwnProperty('file_title')
if (!Array.isArray(files[i])) {
if (typeof files[i]['file_title'] !== 'undefined' && typeof files[i]['file_path'] !== 'undefined') {
await this.urlToPromise(files[i]['file_path']).then(response=>{
if (!folderName)
zip.file(files[i]['file_title'] + '.' + returnExtFromImage(files[i]['file_path']), response, { base64: true, binary: true });
else
tempFolder.file(files[i]['file_title'] + '.' + returnExtFromImage(files[i]['file_path']), response, { base64: true, binary: true });
})
}
} else if (Array.isArray(files[i])) {
zip = this.makezip(files[i], zip, i);
}
}
return zip;
}
urlToPromise(url) {
return new Promise(function (resolve, reject) {
JSZipUtils.getBinaryContent(url, function (err, data) {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
Whenever you use reject in a Promise constructor it will trigger the catch method of the Promise instance. Therefore, you need to add a catch handler when you call urlToPromise, like this:
this.urlToPromise(files[i]['file_path']).then(response=>{
if (!folderName)
zip.file(files[i]['file_title'] + '.' + returnExtFromImage(files[i]['file_path']), response, { base64: true, binary: true });
else
tempFolder.file(files[i]['file_title'] + '.' + returnExtFromImage(files[i]['file_path']), response, { base64: true, binary: true });
}).catch(error => {
// do something with the error
})
Use await inside async function instead of then/catch. You can use try catch statement to catch the error.
async makezip(files, zip, folderName = null) {
if (folderName) var tempFolder = zip.folder(folderName);
for (var i in files) {
files[i].hasOwnProperty('file_title');
if (!Array.isArray(files[i])) {
if (
typeof files[i]['file_title'] !== 'undefined' &&
typeof files[i]['file_path'] !== 'undefined'
) {
try {
const response = await this.urlToPromise(files[i]['file_path']);
if (!folderName)
zip.file(
files[i]['file_title'] +
'.' +
returnExtFromImage(files[i]['file_path']),
response,
{ base64: true, binary: true }
);
else
tempFolder.file(
files[i]['file_title'] +
'.' +
returnExtFromImage(files[i]['file_path']),
response,
{ base64: true, binary: true }
);
} catch (error) {
// handle error
}
}
} else if (Array.isArray(files[i])) {
zip = this.makezip(files[i], zip, i);
}
}
return zip;
}
I am answering my own question i was missing await for recursive function.
var zip = new JSZip();
await this.makezip(files, zip).then(zip=>{
zip.generateAsync({ type: "blob" }).then(function (content) {
if (downloadName) {
FileSaver.saveAs(content, downloadName + '.zip');
} else {
FileSaver.saveAs(content, 'All.zip');
}
});
});
async makezip(files, zip, folderName = null) {
/*if folder name exist in props to create new nested folders*/
if (folderName)
var tempFolder = zip.folder(folderName);
for (var i in files) {
files[i].hasOwnProperty('file_title')
if (!Array.isArray(files[i])) {
if (typeof files[i]['file_title'] !== 'undefined' && typeof files[i]['file_path'] !== 'undefined') {
await this.urlToPromise(files[i]['file_path']).then(response=>{
if (!folderName)
zip.file(files[i]['file_title'] + '.' + returnExtFromImage(files[i]['file_path']), response, { base64: true, binary: true });
else
tempFolder.file(files[i]['file_title'] + '.' + returnExtFromImage(files[i]['file_path']), response, { base64: true, binary: true });
}).catch(err=>{
});
}
}
else if (Array.isArray(files[i])) {
/*recursive loop for nested folders files*/
await this.makezip(files[i], zip, i);
}
}
return zip;
}
async urlToPromise(url) {
return await new Promise(function (resolve, reject) {
JSZipUtils.getBinaryContent(url, function (err, data) {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
That usage of Promise helps you.
function sureify<T, U = Error>(promise: Promise<T>) {
return promise
.then((data) => [data, undefined] as [data: T, error: undefined])
.catch((error: U | undefined) =>
Promise.resolve([undefined, error] as [data: undefined, error: U])
);
}
// Convert from Promise
const [response, error] = await sureify(urlToPromise("url"))

Promise returned by NodeJS Async function is undefined

When I call sendText, the promise returned by callSendAPI returns as undefined, logged on the console like so:
Promise return from callSendAPI undefined
I have read up on promises and checked a lot of stack overflow questions, but I haven't been able to grasp which part of my code is wrong. The message sends fine, but the undefined return has the effect of causing await in higher functions to not work correctly.
What am I doing incorrectly in constructing my promise which is causing it to return as undefined?
var request = require('request-promise-native');
module.exports = {
callSendAPI : function (sender_psid,response) {
return new Promise(async function(resolve,reject) {
// Construct the message body
let request_body = {
"recipient": {
"id": sender_psid
},
"message": response
}
// Send the HTTP request to the Messenger Platform
try {
var a = await request({
"uri": "https://graph.facebook.com/v2.6/me/messages",
"qs": { "access_token": PAGE_ACCESS_TOKEN },
"method": "POST",
"json": request_body
})
} catch(e) {
console.error("Unable to send message:" + e);
return reject(e);
}
console.log('message sent!')
resolve();
});
},
sendText : function(sender_psid,text) {
return new Promise(async function(resolve,reject) {
var response = { "text": `${text}` };
try {
var a = await module.exports.callSendAPI(sender_psid,response);
console.log("Promise return from callSendAPI " + a);
} catch(e) {
console.error(e);
return reject();
}
console.log("message sent--------------------");
resolve();
});
}
}
Here's a re-write that simplifies your implementation and correctly resolves the promise with a value:
var request = require('request-promise-native');
module.exports = {
async callSendAPI (sender_psid, response) {
// Construct the message body
let request_body = {
recipient: {
id: sender_psid
},
message: response
};
// Send the HTTP request to the Messenger Platform
try {
var a = await request({
uri: "https://graph.facebook.com/v2.6/me/messages",
qs: { access_token: PAGE_ACCESS_TOKEN },
method: "POST",
json: request_body
});
console.log('message sent!');
return a;
} catch(e) {
console.error("Unable to send message:" + e);
throw e;
}
},
async sendText (sender_psid, text) {
var response = { text: String(text) };
try {
var a = await module.exports.callSendAPI(sender_psid,response);
console.log("Promise return from callSendAPI " + a);
console.log("message sent--------------------");
return a;
} catch(e) {
console.error(e);
throw e;
}
}
};
As suggested by #jfriend00 you can simply return the promise generated by request() rather than wrapping it in a try-catch, optionally logging each scenario by chaining a .then() like this:
var request = require('request-promise-native');
module.exports = {
async callSendAPI (sender_psid, response) {
// Construct the message body
let request_body = {
recipient: {
id: sender_psid
},
message: response
};
// Send the HTTP request to the Messenger Platform
return request({
uri: 'https://graph.facebook.com/v2.6/me/messages',
qs: { access_token: PAGE_ACCESS_TOKEN },
method: 'POST',
json: request_body
}).then(value => {
console.log('message sent!');
return value;
}, error => {
console.error('Unable to send message:', error);
throw error;
});
},
async sendText (sender_psid, text) {
var response = { text: String(text) };
return module.exports.callSendAPI(sender_psid, response).then(value => {
console.log('Promise return from callSendAPI', value);
console.log('message sent--------------------');
return value;
}, error => {
console.error(error);
throw error;
});
}
};

Javascript function returned an undefined value in NodeJs (Express) [duplicate]

I currently have a function that is called from my router:
router.js:
var result = Api.getUser();
console.log("Result: " + result);
api.js
exports.getUser = function(req, result) {
request.get({
uri: URL + '/user/me/',
headers: {Authorization: 'bearer ' + req.user.accessToken},
json: true
}, function(e, r, body) {
console.log("e: " + e + " body: %j", body);
if(e) {
return "{error: true}";
} else {
return body;
}
});
};
The problem I am having is that I am getting the log "Result: undefined" first.
Is there a way to hold the function getUser from returning until the function for get finishes?
Promises are awesome, I would suggest looking into them. However, a simple callback will do the trick
api:
exports.getUser = function(req, result, callback) {
request.get({
uri: URL + '/user/me/',
headers: {Authorization: 'bearer ' + req.user.accessToken},
json: true
}, function(e, r, body) {
if(e) {
callback({error: true});
} else {
callback(body)
}
});
};
router:
var result
Api.getUser(req, result, function (response) {
result = response
console.log(result)
});
You are dealing with asynchronous code. There are a couple ways to solve this problem.
With A Promise
// api.js
var Promise = require('bluebird');
var request = require('request');
var getP = Promise.promisify(request.get.bind(request));
exports.getUser = function(accessToken) {
return getP({
uri: URL + '/user/me/',
headers: {Authorization: 'bearer ' + accessToken},
json: true
}).spread(function(e, r, body) {
console.log("e: " + e + " body: %j", body);
if(e) {
return Promise.reject("{error: true}");
} else {
return Promise.resolve(body);
}
});
};
// main.js
api.getUser(req.user.accessToken)
.then(console.log.bind(console, "Result: "))
.catch(console.error.bind(console));
With A Callback
// api.js
var request = require('request');
exports.getUser = function(accessToken, callback) {
request.get({
uri: URL + '/user/me/',
headers: {Authorization: 'bearer ' + accessToken},
json: true
}, function(e, r, body) {
console.log("e: " + e + " body: %j", body);
if(e) {
callback("{error: true}");
} else {
callback(null, body);
}
});
};
// main.js
api.getUser(req.user.accessToken, function (err, result) {
if (err) return console.error(err);
console.log("Result: " + result);
});
The nice thing about the promise API is that you only ever need to check for errors once, in your final .catch handler. In the callback style if you need to keep making additional asynchronous calls then you'll have to keep nesting callbacks and checking if (err) return console.error(err) in every single callback.
You can't return from an async function, you use a callback:
exports.getUser = function(req, result, callback) {
request.get({
uri: URL + '/user/me/',
headers: {Authorization: 'bearer ' + req.user.accessToken},
json: true
}, function(e, r, body) {
if(e) {
callback({error: true});
} else {
callback(body);
}
});
};
Api.getUser(req, result, function(user) {
console.log(user);
});

jQuery Deferred: How to compose callbacks that depend on each other? [duplicate]

I'm new to promises and writing network code using requests and promises in NodeJS.
I would like to remove these nested promises and chain them instead, but I'm not sure how I'd go about it/whether it is the right way to go.
exports.viewFile = function(req, res) {
var fileId = req.params.id;
boxContentRequest('files/' + fileId + '/content', req.user.box.accessToken)
.then(function(response) {
boxViewerRequest('documents', {url: response.request.href}, 'POST')
.then(function(response) {
boxViewerRequest('sessions', {document_id: response.body.id}, 'POST')
.then(function(response) {
console.log(response);
});
});
});
};
This is the request code:
var baseContentURL = 'https://api.box.com/2.0/';
var baseViewerURL = 'https://view-api.box.com/1/';
function boxContentRequest(url, accessToken) {
return new Promise(function (resolve, reject) {
var options = {
url: baseContentURL + url,
headers: {
Authorization: 'Bearer ' + accessToken,
}
};
request(options, function (err, res) {
if (err) {
return reject(err);
} else if (res.statusCode !== 200) {
err = new Error("Unexpected status code: " + res.statusCode);
err.res = res;
return reject(err);
}
resolve(res);
});
});
}
function boxViewerRequest(url, body, method) {
return new Promise(function (resolve, reject) {
var options = {
method: method,
url: baseViewerURL + url,
headers: {
Authorization: 'Token ' + config.box.viewerApiKey
},
json: body
};
request(options, function (err, res, body) {
if (err) {
return reject(err);
} else if (res.statusCode !== 200 && res.statusCode !== 201 && res.statusCode !== 202) {
err = new Error("Unexpected status code: " + res.statusCode);
err.res = res;
return reject(err);
}
resolve(res, body);
});
});
}
Any insight would be appreciated.
From every then callback, you will need to return the new promise:
exports.viewFile = function(req, res) {
var fileId = req.params.id;
boxContentRequest('files/' + fileId + '/content', req.user.box.accessToken)
.then(function(response) {
return boxViewerRequest('documents', {url: response.request.href}, 'POST');
})
.then(function(response) {
return boxViewerRequest('sessions', {document_id: response.body.id}, 'POST');
})
.then(function(response) {
console.log(response);
});
};
The promise that is returned by the .then() call will then resolve with the value from the "inner" promise, so that you easily can chain them.
Generic pattern:
somePromise.then(function(r1) {
return nextPromise.then(function(r2) {
return anyValue;
});
}) // resolves with anyValue
||
\||/
\/
somePromise.then(function(r1) {
return nextPromise;
}).then(function(r2) {
return anyValue;
}) // resolves with anyValue as well
Promise.prototype.then is designed to return another promise, so that you can chain them.
The handler function passed to .then() can return a normal value, like a number or string or object, and this value will get passed on to the next handler of .then().
One option is to have boxViewerRequestSync be a synchronous function that returns a response object:
boxContentRequest('files/' + fileId + '/content', req.user.box.accessToken)
.then(function(response) {
return boxViewerRequestSync('documents', {url: response.request.href}, 'POST')
})
.then(function(response) { // this `response` is returned by `boxViewerRequestSync`
return boxViewerRequestSync('sessions', {document_id: response.body.id}, 'POST')
})
.then(function(response) {
console.log(response);
})
But of course your boxViewerRequest is asynchronous and returns a promise instead. In that case, the handler function passed to .then() could also return a completely unrelated Promise. This new promise is executed synchronously, and once it is resolved/rejected, its result is passed on to the next handler.
boxContentRequest('files/' + fileId + '/content', req.user.box.accessToken)
.then(function(response) {
return boxViewerRequest('documents', {url: response.request.href}, 'POST')
})
.then(function(response) { // this `response` is the result of resolving the promise returned by `boxViewerRequest`
return boxViewerRequest('sessions', {document_id: response.body.id}, 'POST')
})
.then(function(response) {
console.log(response);
})
Keeping track of all the promises is confusing, but the bottom line is this: Promise.prototype.then will always return a Promise object, but the handler function passed to Promise.prototype.then can return anything, even undefined, or even another Promise. Then that value, or the value of the resolved Promise, is passed to the next handler function.

Web Animations API w/ Promise Pattern - Code Cleanliness [duplicate]

I'm new to promises and writing network code using requests and promises in NodeJS.
I would like to remove these nested promises and chain them instead, but I'm not sure how I'd go about it/whether it is the right way to go.
exports.viewFile = function(req, res) {
var fileId = req.params.id;
boxContentRequest('files/' + fileId + '/content', req.user.box.accessToken)
.then(function(response) {
boxViewerRequest('documents', {url: response.request.href}, 'POST')
.then(function(response) {
boxViewerRequest('sessions', {document_id: response.body.id}, 'POST')
.then(function(response) {
console.log(response);
});
});
});
};
This is the request code:
var baseContentURL = 'https://api.box.com/2.0/';
var baseViewerURL = 'https://view-api.box.com/1/';
function boxContentRequest(url, accessToken) {
return new Promise(function (resolve, reject) {
var options = {
url: baseContentURL + url,
headers: {
Authorization: 'Bearer ' + accessToken,
}
};
request(options, function (err, res) {
if (err) {
return reject(err);
} else if (res.statusCode !== 200) {
err = new Error("Unexpected status code: " + res.statusCode);
err.res = res;
return reject(err);
}
resolve(res);
});
});
}
function boxViewerRequest(url, body, method) {
return new Promise(function (resolve, reject) {
var options = {
method: method,
url: baseViewerURL + url,
headers: {
Authorization: 'Token ' + config.box.viewerApiKey
},
json: body
};
request(options, function (err, res, body) {
if (err) {
return reject(err);
} else if (res.statusCode !== 200 && res.statusCode !== 201 && res.statusCode !== 202) {
err = new Error("Unexpected status code: " + res.statusCode);
err.res = res;
return reject(err);
}
resolve(res, body);
});
});
}
Any insight would be appreciated.
From every then callback, you will need to return the new promise:
exports.viewFile = function(req, res) {
var fileId = req.params.id;
boxContentRequest('files/' + fileId + '/content', req.user.box.accessToken)
.then(function(response) {
return boxViewerRequest('documents', {url: response.request.href}, 'POST');
})
.then(function(response) {
return boxViewerRequest('sessions', {document_id: response.body.id}, 'POST');
})
.then(function(response) {
console.log(response);
});
};
The promise that is returned by the .then() call will then resolve with the value from the "inner" promise, so that you easily can chain them.
Generic pattern:
somePromise.then(function(r1) {
return nextPromise.then(function(r2) {
return anyValue;
});
}) // resolves with anyValue
||
\||/
\/
somePromise.then(function(r1) {
return nextPromise;
}).then(function(r2) {
return anyValue;
}) // resolves with anyValue as well
Promise.prototype.then is designed to return another promise, so that you can chain them.
The handler function passed to .then() can return a normal value, like a number or string or object, and this value will get passed on to the next handler of .then().
One option is to have boxViewerRequestSync be a synchronous function that returns a response object:
boxContentRequest('files/' + fileId + '/content', req.user.box.accessToken)
.then(function(response) {
return boxViewerRequestSync('documents', {url: response.request.href}, 'POST')
})
.then(function(response) { // this `response` is returned by `boxViewerRequestSync`
return boxViewerRequestSync('sessions', {document_id: response.body.id}, 'POST')
})
.then(function(response) {
console.log(response);
})
But of course your boxViewerRequest is asynchronous and returns a promise instead. In that case, the handler function passed to .then() could also return a completely unrelated Promise. This new promise is executed synchronously, and once it is resolved/rejected, its result is passed on to the next handler.
boxContentRequest('files/' + fileId + '/content', req.user.box.accessToken)
.then(function(response) {
return boxViewerRequest('documents', {url: response.request.href}, 'POST')
})
.then(function(response) { // this `response` is the result of resolving the promise returned by `boxViewerRequest`
return boxViewerRequest('sessions', {document_id: response.body.id}, 'POST')
})
.then(function(response) {
console.log(response);
})
Keeping track of all the promises is confusing, but the bottom line is this: Promise.prototype.then will always return a Promise object, but the handler function passed to Promise.prototype.then can return anything, even undefined, or even another Promise. Then that value, or the value of the resolved Promise, is passed to the next handler function.

Categories

Resources