Is this possible way to return resolve or reject message from one function to another?
As I am writing to pass resolve message in postman whenever my task is completed or reject message when there is some error
But after after writing return it still not returning the resolve message or reject message inside Postman
any idea how this can be resolve?
async function readFile(filePath) {}
async function getAllFile(filePath) {
const paths = await readFile(filePath);
}
async function filterFiles(filePath) {
const paths = await getAllFile(filePath);
}
function addDocument(childProduct){
return new Promise((resolve, reject) => {
Document.create({
name: childProduct,
},
}).then(function (filePath) {
filterFiles(filePath);
let msg = "Document created Succesfully";
return resolve(msg);
})
.catch(function (err) {
return reject("Can't be updated please try again :) " + err);
});
});
}
function updateDoc(data){
return new Promise((resolve, reject) => {
Document.update({
name: data.name,
}
where: {
product_id: data,
},
})
}).then(function (childProduct) {
addDocument(childProduct);
let msg = "Updated Successfully";
return resolve(msg);
})
.catch(function (err) {
return reject("Can't be updated please try again :) " + err);
});
}
Product.findOne and Document.findAll return a Promise, so they can be returned and awaited directly.
You can chain await func1(); await func2(); await func3() in one try{} block, and catch any error that happens in one place :
const filterFiles = async filePath => {
const paths = await getAllFiles(filePath);
// .. Do something else here
return paths // This is a Promise because async functions always return a Promise
}
const findOneDoc = name => Product.findOne({ where: { name } }); // This func returns a Promise
const findAllDocs = product_id => Document.findAll({ // This func returns a Promise too
raw: true,
where: { product_id }
});
(async () => {
try {
const childProduct = await findOneDoc("some_name");
console.log("All good until now!");
const filePath = await findAllDocs(childProduct._id);
console.log("Still good");
const filteredFiles = await filterFiles(filePath);
console.log("All went well.");
console.log(filteredFiles);
} catch (err) {
// If any of the functions above fails, the try{} block will break and the error will be caught here.
console.log(`Error!`, err);
}
})();
There are few things I would like to mention.
When you create a promise, it should have resolve() and reject() inside it.
for ex-
function testPromise() {
return new Promise((resolve, reject) => {
// your logic
// The followin if-else is not nessesary, its just for an illustration
if (Success condition met) {
resolve(object you want to return);
}else {
reject(error);
// you can add error message in this error as well
}
});
}
// Calling the method with await
let obj = await testPromise()
// OR call with then, but its better to go with await
testPromise().then((obj)=>{
// Access obj here
})
In the method which you have written, You have applied .then() method to non promise object. You have to complete the promise block first with resolve() and reject() inside it. Then you can return that promise from a function, use it in async function Or apply .then() block on it.
Also you don't need to add return statement to resolve() and reject() statement. The system will take care of it.
You can also use try catch block inside a promise. Its better to write reject() statement in catch block, if anything goes wrong.
Related
I'm using the async.eachLimit function to control the maximum number of operations at a time.
const { eachLimit } = require("async");
function myFunction() {
return new Promise(async (resolve, reject) => {
eachLimit((await getAsyncArray), 500, (item, callback) => {
// do other things that use native promises.
}, (error) => {
if (error) return reject(error);
// resolve here passing the next value.
});
});
}
As you can see, I can't declare the myFunction function as async because I don't have access to the value inside the second callback of the eachLimit function.
You're effectively using promises inside the promise constructor executor function, so this the Promise constructor anti-pattern.
Your code is a good example of the main risk: not propagating all errors safely. Read why there.
In addition, the use of async/await can make the same traps even more surprising. Compare:
let p = new Promise(resolve => {
""(); // TypeError
resolve();
});
(async () => {
await p;
})().catch(e => console.log("Caught: " + e)); // Catches it.
with a naive (wrong) async equivalent:
let p = new Promise(async resolve => {
""(); // TypeError
resolve();
});
(async () => {
await p;
})().catch(e => console.log("Caught: " + e)); // Doesn't catch it!
Look in your browser's web console for the last one.
The first one works because any immediate exception in a Promise constructor executor function conveniently rejects the newly constructed promise (but inside any .then you're on your own).
The second one doesn't work because any immediate exception in an async function rejects the implicit promise returned by the async function itself.
Since the return value of a promise constructor executor function is unused, that's bad news!
Your code
There's no reason you can't define myFunction as async:
async function myFunction() {
let array = await getAsyncArray();
return new Promise((resolve, reject) => {
eachLimit(array, 500, (item, callback) => {
// do other things that use native promises.
}, error => {
if (error) return reject(error);
// resolve here passing the next value.
});
});
}
Though why use outdated concurrency control libraries when you have await?
I agree with the answers given above and still, sometimes it's neater to have async inside your promise, especially if you want to chain several operations returning promises and avoid the then().then() hell. I would consider using something like this in that situation:
const operation1 = Promise.resolve(5)
const operation2 = Promise.resolve(15)
const publishResult = () => Promise.reject(`Can't publish`)
let p = new Promise((resolve, reject) => {
(async () => {
try {
const op1 = await operation1;
const op2 = await operation2;
if (op2 == null) {
throw new Error('Validation error');
}
const res = op1 + op2;
const result = await publishResult(res);
resolve(result)
} catch (err) {
reject(err)
}
})()
});
(async () => {
await p;
})().catch(e => console.log("Caught: " + e));
The function passed to Promise constructor is not async, so linters don't show errors.
All of the async functions can be called in sequential order using await.
Custom errors can be added to validate the results of async operations
The error is caught nicely eventually.
A drawback though is that you have to remember putting try/catch and attaching it to reject.
BELIEVING IN ANTI-PATTERNS IS AN ANTI-PATTERN
Throws within an async promise callback can easily be caught.
(async () => {
try {
await new Promise (async (FULFILL, BREAK) => {
try {
throw null;
}
catch (BALL) {
BREAK (BALL);
}
});
}
catch (BALL) {
console.log ("(A) BALL CAUGHT", BALL);
throw BALL;
}
}) ().
catch (BALL => {
console.log ("(B) BALL CAUGHT", BALL);
});
or even more simply,
(async () => {
await new Promise (async (FULFILL, BREAK) => {
try {
throw null;
}
catch (BALL) {
BREAK (BALL);
}
});
}) ().
catch (BALL => {
console.log ("(B) BALL CAUGHT", BALL);
});
I didn't realized it directly by reading the other answers, but what is important is to evaluate your async function to turn it into a Promise.
So if you define your async function using something like:
let f = async () => {
// ... You can use await, try/catch, throw syntax here (see answer of Vladyslav Zavalykhatko) ..
};
your turn it into a promise using:
let myPromise = f()
You can then manipulate is as a Promise, using for instance Promise.all([myPromise])...
Of course, you can turn it into a one liner using:
(async () => { code with await })()
static getPosts(){
return new Promise( (resolve, reject) =>{
try {
const res = axios.get(url);
const data = res.data;
resolve(
data.map(post => ({
...post,
createdAt: new Date(post.createdAt)
}))
)
} catch (err) {
reject(err);
}
})
}
remove await and async will solve this issue. because you have applied Promise object, that's enough.
I'm using the async.eachLimit function to control the maximum number of operations at a time.
const { eachLimit } = require("async");
function myFunction() {
return new Promise(async (resolve, reject) => {
eachLimit((await getAsyncArray), 500, (item, callback) => {
// do other things that use native promises.
}, (error) => {
if (error) return reject(error);
// resolve here passing the next value.
});
});
}
As you can see, I can't declare the myFunction function as async because I don't have access to the value inside the second callback of the eachLimit function.
You're effectively using promises inside the promise constructor executor function, so this the Promise constructor anti-pattern.
Your code is a good example of the main risk: not propagating all errors safely. Read why there.
In addition, the use of async/await can make the same traps even more surprising. Compare:
let p = new Promise(resolve => {
""(); // TypeError
resolve();
});
(async () => {
await p;
})().catch(e => console.log("Caught: " + e)); // Catches it.
with a naive (wrong) async equivalent:
let p = new Promise(async resolve => {
""(); // TypeError
resolve();
});
(async () => {
await p;
})().catch(e => console.log("Caught: " + e)); // Doesn't catch it!
Look in your browser's web console for the last one.
The first one works because any immediate exception in a Promise constructor executor function conveniently rejects the newly constructed promise (but inside any .then you're on your own).
The second one doesn't work because any immediate exception in an async function rejects the implicit promise returned by the async function itself.
Since the return value of a promise constructor executor function is unused, that's bad news!
Your code
There's no reason you can't define myFunction as async:
async function myFunction() {
let array = await getAsyncArray();
return new Promise((resolve, reject) => {
eachLimit(array, 500, (item, callback) => {
// do other things that use native promises.
}, error => {
if (error) return reject(error);
// resolve here passing the next value.
});
});
}
Though why use outdated concurrency control libraries when you have await?
I agree with the answers given above and still, sometimes it's neater to have async inside your promise, especially if you want to chain several operations returning promises and avoid the then().then() hell. I would consider using something like this in that situation:
const operation1 = Promise.resolve(5)
const operation2 = Promise.resolve(15)
const publishResult = () => Promise.reject(`Can't publish`)
let p = new Promise((resolve, reject) => {
(async () => {
try {
const op1 = await operation1;
const op2 = await operation2;
if (op2 == null) {
throw new Error('Validation error');
}
const res = op1 + op2;
const result = await publishResult(res);
resolve(result)
} catch (err) {
reject(err)
}
})()
});
(async () => {
await p;
})().catch(e => console.log("Caught: " + e));
The function passed to Promise constructor is not async, so linters don't show errors.
All of the async functions can be called in sequential order using await.
Custom errors can be added to validate the results of async operations
The error is caught nicely eventually.
A drawback though is that you have to remember putting try/catch and attaching it to reject.
BELIEVING IN ANTI-PATTERNS IS AN ANTI-PATTERN
Throws within an async promise callback can easily be caught.
(async () => {
try {
await new Promise (async (FULFILL, BREAK) => {
try {
throw null;
}
catch (BALL) {
BREAK (BALL);
}
});
}
catch (BALL) {
console.log ("(A) BALL CAUGHT", BALL);
throw BALL;
}
}) ().
catch (BALL => {
console.log ("(B) BALL CAUGHT", BALL);
});
or even more simply,
(async () => {
await new Promise (async (FULFILL, BREAK) => {
try {
throw null;
}
catch (BALL) {
BREAK (BALL);
}
});
}) ().
catch (BALL => {
console.log ("(B) BALL CAUGHT", BALL);
});
I didn't realized it directly by reading the other answers, but what is important is to evaluate your async function to turn it into a Promise.
So if you define your async function using something like:
let f = async () => {
// ... You can use await, try/catch, throw syntax here (see answer of Vladyslav Zavalykhatko) ..
};
your turn it into a promise using:
let myPromise = f()
You can then manipulate is as a Promise, using for instance Promise.all([myPromise])...
Of course, you can turn it into a one liner using:
(async () => { code with await })()
static getPosts(){
return new Promise( (resolve, reject) =>{
try {
const res = axios.get(url);
const data = res.data;
resolve(
data.map(post => ({
...post,
createdAt: new Date(post.createdAt)
}))
)
} catch (err) {
reject(err);
}
})
}
remove await and async will solve this issue. because you have applied Promise object, that's enough.
I have an internal API that I would like to post data. Depends on some cases, I am seeing errors. So what I would like to do is to call it again if there is an error occurred.
What I did was to create a counter to pass it to the function and call the function recursively as below. This gives me the error as below:
UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
Here is how I call the function:
....
private RETRY_API = 1;
....
try {
await this.callAPI(request, this.RETRY_API);
} catch (error) {
console.log('error', error);
}
This program never comes to the catch block above.
And here is my actual function that I call the API:
private async callAPI(request, retry) {
return new Promise((resolve, reject) => {
someService.postApiRequest('api/url', request, async(err: any, httpCode: number, data) => {
if (this.RETRY_API == 2) {
return reject(err);
} else if (err) {
this.callAPI(request, retry);
this.RETRY_API++;
} else if ( httpCode !== 200 ) {
this.RETRY_API = 2;
// some stuff
} else {
this.RETRY_API = 2;
// some stuff
return resolve(data);
}
});
})
}
Not sure what I am missing. If there is a better way to call the API twice if an error occurred, that would be great if you let me know.
Let's organize a little differently. First, a promise-wrapper for the api...
private async callAPI(request) {
return new Promise((resolve, reject) => {
someService.postApiRequest('api/url', request,(err: any, httpCode: number, data) => {
err ? reject(err) : resolve(data);
});
});
}
A utility function to use setTimeout with a promise...
async function delay(t) {
return new Promise(resolve => setTimeout(resolve, t));
}
Now, a function that calls and retries with delay...
private async callAPIWithRetry(request, retryCount=2, retryDelay=2000) {
try {
return await callAPI(request);
} catch (error) {
if (retryCount <= 0) throw err;
await delay(retryDelay);
return callAPIWithRetry(request, retryCount-1, retryDelay);
}
}
If you can't force a failure on the api to test the error path some other way, you can at least try this...
private async callAPIWithRetry(request, retryCount=2, retryDelay=2000) {
try {
// I hate to do this, but the only way I can test the error path is to change the code here to throw an error
// return await callAPI(request);
await delay(500);
throw("mock error");
} catch (error) {
if (retryCount <= 0) throw err;
await delay(retryDelay);
return callAPIWithRetry(request, retryCount-1, retryDelay);
}
}
It looks like you need to add return await to the beginning of the line this.callAPI(request, retry); in callAPI function.
Similarly there are some condition blocks that doesn't resolve or reject the promise. While it might work okay, it's considered bad practice. You want to either resolve or reject a promise.
I've accomplished calling an API a second time when I received an error by using axios' interceptors functions.
Here is a code snippet you can review:
axios.interceptors.response.use(
// function called on a successful response 2xx
function (response) {
return response;
},
// function called on an error response ( not 2xx )
async function (error) {
const request = error.config as AxiosRequestConfig;
// request is original API call
// change something about the call and try again
// request.headers['Authorization'] = `Bearer DIFFERENT_TOKEN`;
// return axios(request)
// or Call a different API
// const new_data = await axios.get(...).then(...)
// return new_data
// all else fails return the original error
return Promise.reject(error)
}
);
Try replacing
if (this.RETRY_API == 2)
with
if (this.RETRY_API > 1)
Im trying to use async await on a function that returns a promise but the out put im getting is Promise { <pending> }. In here im using function called convertFiletoPDF which returns a promise. I need to get the output (the path that i have mention in resolve() ).
When i use it as
convertFiletoPDF(file).then((result) => {
console.log(result);
}).catch((err)=>{
console.log(err);
});
it gives the expected result.Whats wrong with the code below? im quite new to these async await and promises.
function convertFiletoPDF(file) {
return new Promise(function(resolve, reject) {
unoconv.convert(file, "pdf", function(
err,
result
) {
if (err) {
reject(err);
}
let File = file.substring(file.lastIndexOf("/")+1,file.lastIndexOf("."));
// result is returned as a Buffer
fs.writeFile(__dirname+"/files/converted/"+File+".pdf", result, error => {
/* handle error */
if (err) reject(error);
else resolve("./files/converted/"+File+".pdf");
});
});
});
}
async function myfunc(file){
let res = await convertFiletoPDF(file);
return res;
}
let res = myfunc(file);
console.log(res);
The return value of an async function is a promise, so naturally that's what your console.log outputs. You need to either consume the result via await (within another async function) or use then/catch (within another async function).
This is what you're currently doing:
function convertFiletoPDF(file) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, 400, "Done");
});
}
async function myfunc(file){
let res = await convertFiletoPDF(file);
return res;
}
let res = myfunc("some file");
console.log(res);
You need to be doing either this:
function convertFiletoPDF(file) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, 400, "Done");
});
}
async function myfunc(file){
let res = await convertFiletoPDF(file);
return res;
}
(async() => {
try {
let res = await myfunc("some file");
console.log(res);
} catch (e) {
// Deal with the fact there was an error
}
})();
or with then and catch:
function convertFiletoPDF(file) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, 400, "Done");
});
}
async function myfunc(file){
let res = await convertFiletoPDF(file);
return res;
}
myfunc("some file")
.then(res => {
console.log(res);
})
.catch(e => {
// Deal with the fact there was an error
});
convertFiletoPDF()
This function run and returned a Promise. This is fine.
myfunc()
Lets say myfunc takes 10 seconds. Javascript starts to wait newly created thread result from libuv via event loop mechanism. So, Javascript says, "That one is async, I will not wait, when it finishes it will let me know and i will run my then callback and then I will proceed with its output."
Javascript keeps his promise. Tries to run next below lines. myFunch is still working. Output is not ready yet. Returns undefined.
let res = myfunc(file);
console.log(res);
You get undefined.
Someone might find this example from my code useful. You can wrap it in a promise and then resolve the custom promise and then call another promise to confirm the receipt of the original web3 call.
return new Promise((resolve, reject) => {
tokenContract.methods.approve(
exchangeAddress,
BIG_NUMBER_1e50
)
.send({ from })
.once('transactionHash')
.once('receipt', receipt => resolve(receipt))
.on('confirmation')
.on('error', err => reject(err))
.then( receipt => // will be fired once the receipt its mined
console.log(receipt),
);
});
Im trying to use async await on a function that returns a promise but the out put im getting is Promise { <pending> }. In here im using function called convertFiletoPDF which returns a promise. I need to get the output (the path that i have mention in resolve() ).
When i use it as
convertFiletoPDF(file).then((result) => {
console.log(result);
}).catch((err)=>{
console.log(err);
});
it gives the expected result.Whats wrong with the code below? im quite new to these async await and promises.
function convertFiletoPDF(file) {
return new Promise(function(resolve, reject) {
unoconv.convert(file, "pdf", function(
err,
result
) {
if (err) {
reject(err);
}
let File = file.substring(file.lastIndexOf("/")+1,file.lastIndexOf("."));
// result is returned as a Buffer
fs.writeFile(__dirname+"/files/converted/"+File+".pdf", result, error => {
/* handle error */
if (err) reject(error);
else resolve("./files/converted/"+File+".pdf");
});
});
});
}
async function myfunc(file){
let res = await convertFiletoPDF(file);
return res;
}
let res = myfunc(file);
console.log(res);
The return value of an async function is a promise, so naturally that's what your console.log outputs. You need to either consume the result via await (within another async function) or use then/catch (within another async function).
This is what you're currently doing:
function convertFiletoPDF(file) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, 400, "Done");
});
}
async function myfunc(file){
let res = await convertFiletoPDF(file);
return res;
}
let res = myfunc("some file");
console.log(res);
You need to be doing either this:
function convertFiletoPDF(file) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, 400, "Done");
});
}
async function myfunc(file){
let res = await convertFiletoPDF(file);
return res;
}
(async() => {
try {
let res = await myfunc("some file");
console.log(res);
} catch (e) {
// Deal with the fact there was an error
}
})();
or with then and catch:
function convertFiletoPDF(file) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, 400, "Done");
});
}
async function myfunc(file){
let res = await convertFiletoPDF(file);
return res;
}
myfunc("some file")
.then(res => {
console.log(res);
})
.catch(e => {
// Deal with the fact there was an error
});
convertFiletoPDF()
This function run and returned a Promise. This is fine.
myfunc()
Lets say myfunc takes 10 seconds. Javascript starts to wait newly created thread result from libuv via event loop mechanism. So, Javascript says, "That one is async, I will not wait, when it finishes it will let me know and i will run my then callback and then I will proceed with its output."
Javascript keeps his promise. Tries to run next below lines. myFunch is still working. Output is not ready yet. Returns undefined.
let res = myfunc(file);
console.log(res);
You get undefined.
Someone might find this example from my code useful. You can wrap it in a promise and then resolve the custom promise and then call another promise to confirm the receipt of the original web3 call.
return new Promise((resolve, reject) => {
tokenContract.methods.approve(
exchangeAddress,
BIG_NUMBER_1e50
)
.send({ from })
.once('transactionHash')
.once('receipt', receipt => resolve(receipt))
.on('confirmation')
.on('error', err => reject(err))
.then( receipt => // will be fired once the receipt its mined
console.log(receipt),
);
});