Iterative promise if error - node.js

Below I have a function that returns a promise, where execAsyc will throw an error if the arrayItem is in valid, if it's invalid we move on to the next. Is there a iterative way to do this?
function performAction () {
return Promise.resolve()
.then(() => {
return execAsync(arrayItem[0])
})
.catch(() => {
return execAsync(arrayItem[1])
})
.catch(() => {
return execAsync(arrayItem[2])
})
}

Using Array#reduce should help you out:
function performAction() {
return arrayItem.reduce((prev, item) => {
return prev.catch(() => execAsync(item))
}, Promise.reject()) // start out with a rejected promise, so that execAsync is called for the first item in your array
}
This function returns a promise, that rejects if execAsync failed for all items in the array, or resolves with the result from execAsync for the first valid item.

Related

Using promise .then return promise and wrap previous response

As I understand, promise.then returns a new promise. But how to return this promise with a value. Here is my sample code
function sleep(input, timeout) {
return new Promise(resolve => {
setTimeout(resolve(input), timeout)});
}
async function main() {
sleep(['a','b'],1000)
.then(([first, second]) => {
console.log(first)
console.log(second);
return [first+'t', second];
});
}
main()
.then(res => {
console.log(res);
})
The log output
a
b
undefined
Expected
a
b
['at', 'b']
In console.log(res) you want to print the value returned by sleep.then(...) inside the main() function. However, that function is not returning that value. In fact, it isn't returning anything, so res is undefined.
Inside main(), you should return sleep.then(...). That way, res will be the value which is returned by that promise.
function sleep(input, timeout) {
return new Promise(resolve => {
setTimeout(resolve(input), timeout)});
}
async function main() {
return sleep(['a','b'],1000)
.then(([first, second]) => {
console.log(first)
console.log(second);
return [first+'t', second];
});
}
main()
.then(res => {
console.log(res);
})

Handling nested promises

I am trying to reject a value inside a nested promise but it doesn't seem to actually reject it correctly. In the code below, when I get an error from promiseVariable, it doesn't reject with the error. In the promiseVariable.catch statement, I have reject(err). Shouldn't that reject with that error for the whole promise?
return new Promise((resolve, reject) => {
const user = anotherFunction();
if (!user) {
promiseVariable.then((data) => {
user = data;
}).catch((err) => {
reject(err)
})
}
resolve(user);
});
Because it will start the promiseVariable chain and jump over to resolve. In the .then, you should resolve there, or put an else.
return new Promise((resolve, reject) => {
const user = anotherFunction();
if (!user) {
promiseVariable
.then(resolve)
.catch(reject);
} else {
resolve(user);
}
});
It seems you're over-promising, if that's a word. You can just "await" for your other promise to complete.
Here, anotherFunction is a simulated Promise, where after 3 seconds it returns a valid object for your conditional if(!user).
You can try changing resolve({user: 1234}) with a false (or falsy) value to see its rejection.
function anotherFunction() {
return new Promise((resolve,reject) => {
setTimeout(() => resolve({user: 1234}), 3000)
});
}
async function mainFunction() {
const user = await anotherFunction();
return user || {error: 404};
}
mainFunction().then(result => console.log(result));

async function resolve with Promise but returns undefined

I'm reading data from db with using await so I used Promise but the function seems to return nothing
async function read() {
return new Promise((resolve, reject) => {
const db = new DB();
db
.read()
.then(result => {
resolve(result);
}).catch(() => {
reject('db-error');
});
});
}
(async () => {
const data = await read();
console.log(data); // undefined
})();
How can I make read() return result?
You are making it more complicated than it has to be. If you are already using an API that returns a promise then there is no need to use the promise constructor yourself.
And declaring a function as async is only necessary if you are using await in it to deal with promises.
So either do:
function read() {
const db = new DB();
return db
.read()
.catch(() => {
return 'db-error';
});
}
Or
async function read() {
const db = new DB();
try {
return await db.read();
} catch(error) {
return 'db-error';
}
}
If you are still not getting the value you want then you are not using the database API correctly and you have to read its documentation to figure out how to get back the right data.
The awesome guys who write the MDN Web Docs say that the result of await will be undefined if the promise that is being waited on is rejected: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await#handling_rejected_promises
Check out the following scenario.
This is a simple function that returns a Promise:
function asyncFunc(waitTime) {
return new Promise((resolve, reject) => {
setTimeout(() => {
// say we prefer people who do things in 3 seconds or less
if (waitTime <= 3000) {
resolve('Promise resolved! You\'re fast! :)');
} else {
reject('Promise rejected! You\'re slow! :(');
}
}, waitTime);
});
}
Let's test the function using a method similar to yours:
async function testAsyncFunc(waitTime) {
try {
const result = await asyncFunc(waitTime);
console.log(result);
} catch(error) {
console.error(error.message);
}
}
testAsyncFunc(3000); // Returns `Promise resolved! You're fast! :)`, as expected
testAsyncFunc(3001); // Returns `undefined` instead of `Promise rejected! You're slow! :(`
But since we want the actual rejection error of the asynchronous operation instead of undefined, the solution is to chain catch to the await statement to catch any rejection errors immediately you call the asynchronous function and then throw the error so it can be caught by any catch error handler you may want to use, like so:
async function testAsyncFunc(waitTime) {
try {
const result = await asyncFunc(waitTime)
.catch(error => {
// throw the rejection error so it can be handled by the catch block below
throw new Error(error);
});
// if no errors
console.log(result);
} catch(error) {
console.error(error.message);
}
}
testAsyncFunc(3001); // Returns the expected result: `Promise rejected! You're slow! :(`

How to break promise chain nested into another promise chain

I am unable to figure out how to break a nested promise chain into a main promise chain. Here is my code :
//Main Promise chain
let promiseMain = Promise.resolve(1)
.then(result => functionA())
.then(result => nestedChain()).catch((error) => {
console.log(error);
})
.then(result => functionC())
//chain error handler
function chainError(err) {
return Promise.reject(err)
};
function nestedChain()
{
stepOne()
.then(stepTwo, chainError)
.then(stepThreee, chainError)
.catch((error) =>
{
console.log(error);
return undefined;
});
}
function stepOne()
{
return chainError("error attempt : 1.00");
}
Once I go into the nestedChain where I throw an error in stepOne() I am able to break this nestedChain. Awesome!
The problem: It also breaks the main promise chain. So.. when it goes into nestedChain() and the error is thrown from stepOne(), functionC from the main promise chain will never be executed because the rejected promise from the nestedChain also break this chain.
You will have to attach with promises chain, do something like this
function nestedChain()
{
stepOne()
.then(stepTwo, chainError)
.then(stepThreee, chainError)
.catch ((error) => {
console.log(error);
return undefined;
})
}
Promise are implemented to wait for something which take more time. You just need to implement promise correctly.
For example if we have 3 function returning promise and one nested function also returning promise, this is how it's implemented:
functionA()
.then( result => {
return functionB();
})
.then( result => {
return nestedFunct();
})
.then( result => {
return functionC();
})
.then( result => {
console.log(result);
})
.catch( error => {
console.log(`Error in one of the above function`);
});
All the function are of format similar too
function functionA() {
return new Promise( (resilve, reject) => {
resolve('something');
// or
reject('Error');
});
}
Nested function can be like this
function nestedFunc() {
return functionD() // Return promise
.then( result => {
return functionE(); // return promise
})
.then( result => {
return functionF(); // return promise or value
});
}
Main promise chain is not affected by what individual function do as long as they keep returning promise. All individual function can have a local promise chain. Even if an error occurred in nested chain will be catched by catch() in main promise chain.
If i understood you correct, you need to catch error after nested chain promise
Promise.resolve().then(()=> {
console.log('A');
}).then(() => {
return Promise.resolve().then(() => {
console.log('step 1');
}).then(() => {
console.log('step 2');
throw new Error('Step 2 error');
});
}).catch((err) => {
console.log(err);
}).then(() => {
console.log('C');
});

Wait for each promise to be done after continuing loop

Below I have two functions. One of the returns a promise and I want in each and every loop to wait for it to finish first and then move one. As you'll see below the result is not the desired/synchronous. Should I not use async.forEachof
function test(num, callback)
{
console.log("inside function: "+num)
return new Promise((resolve, reject) => {
my.promise(num).then(() => {
console.log("done: "+num)
resolve(callback);
}).catch(e => console.error(e));
}).catch(console.error);
}
function start_function()
{
//stuff
async.forEachOf(arr, function (itm, i, callback){
console.log(i)
test(i, callback).catch(e => console.error(e));
}, function (err) {
console.log("ALL DONE")
});
}
Result:
0
inside function 0
1
inside function 1
2
inside function 2
done: 0
done: 2 //wrong should always be 1, finished before the previous promise.
done: 1 //wrong
ALL DONE
I do not want to use PromiseAll not because I dont want but because I need each promise to wait for the previous one's result, and then start the next one. It is pointless therefore to gather them all and then wait for them to be done in whatever order and to what I need to do.
If I'm not wrong what exactly you are trying to do, but you should avoid passing callback in Promise function and resolving it. You can achieve the same with this code and remove callback from test function as well.
function start_function()
{
//stuff
arr.forEach(async function (itm, i, array){
console.log(i)
try {
await test(i);
}
catch(err){
console.log(err);
}
});
}
Here's how test function may look like,
function test(num)
{
console.log("inside function: "+num)
return new Promise((resolve, reject) => {
my.promise(num).then(() => {
console.log("done: "+num)
resolve();
}).catch(e => {
console.error(e)
reject(e);
});
});
}
What about this approach:
(function loopOnItems(i) {
dummyGoogleAPI.someAsyncMethod(data).then(function (_response) {
// do something with response
})
.catch(function (error) {
console.error(error);
});
if (--i){
loopOnItems(i);
}// decrement i and call loopOnItems again if i > 0
else{
_callback(errors);
}
})(count);
You have some count and we call loopOnItems method till count > 0

Resources