Rejecting a Promise with another new Promise - javascript

Im playing around with promises and i wanted a way of rejecting the promise inside of a then callback. So this is done by either calling throw return or return Promise.reject();. So far so good. You can accomplish this by also calling new Promise.reject(); withou a return.
Can someone explain why does this work?
new Promise((res, rej) => {
setTimeout(() => {
res(200);
}, 2000);
})
.then(() => {
console.log("ok1");
new Promise.reject();
// return Promise.reject();
.then(() => {
console.log("ok2");
})
.catch(() => {
console.log("error");
});

new Promise.reject()
Your code throws an exception. Exceptions cause promises to be rejected.

Because Promise.reject is not a constructor, this code works fine:
new Promise((res, rej) => {
setTimeout(() => {
res(200);
}, 2000);
})
.then(() => {
console.log('ok1')
Promise.reject('error!')
})
.then(() => {
console.log("ok2");
})
.catch(() => {
console.log("error");
});

New Promise.reject throws an error so the code jumps to the catch section with the following error : Promise.reject is not a constructor
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 2000);
}).then((res) => {
console.log(res);
new Promise.reject();
})
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log('error' ,err.message);
});

Related

How do i write promises in javascript

im trying to write a promise but seems to be missing something. here is my code:
const myPromise = new Promise(() => {
setTimeout(() => {
console.log("getting here");
return setinputs({ ...inputs, images: imageAsUrl });
}, 100);
});
myPromise
.then(() => {
console.log("getting here too");
firebase.database().ref(`collection/${idNode}`).set(inputs);
})
.then(() => {
console.log("all is set");
})
.catch((err) => {
console.log(err);
});
if i run the program, the first part of the promise is executing but all .then() functions arent executing. how do i fix this?
In this scheme, the promise callback has one (resolve) or two (resolve,reject) arguments.
let p = new Promise((resolve, reject)=> {
//do something
//resolve the promise:
if (result === "ok") {
resolve(3);
}
else {
reject("Something is wrong");
}
});
p.then(res => {
console.log(res); // "3"
}).catch(err => {
console.error(err); //"Something is wrrong
});
Of course, nowadays you can use async + await in a lot of cases.
You need to resolve the promise, using resolve() and also return the promise from firebase so the next .then in the chain works properly.
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("getting here");
// You have to call resolve for all `.then` methods to be triggered
resolve({ ...inputs, images: imageAsUrl });
}, 100);
});
myPromise
.then((inputs) => {
console.log("getting here too");
// You have to return a promise in a .then function for the next .then to work properly
return firebase.database().ref(`collection/${idNode}`).set(inputs);
})
.then(() => {
console.log("all is set");
})
.catch((err) => {
console.log(err);
});

What is the proper way to use Promise.reject with javascript

I have this following piece of code
new Promise((resolve, reject) => {
resolve(apiRequest(data))
reject(console.log('Error'))
}).then(response)
Both methods (resolve and reject) are being fired but I want to call reject only when something goes wrong.
How can I throw an error if something goes wrong on that case?
I checked that but it seems like I can not use an If statement to do that check.
new Promise((resolve, reject) => {
const printResult = apiRequest(data)
console.log(printResult) //Outputs Promise {<pending>}
resolve(printResult) //Then it works
reject(console.log('Error'))
}).then(response)
What would be the correct approach to reject a promise?
The easiest way would be with an if condition. i.e
new Promise((resolve, reject) => {
// do something...
if(somethingGoodHappened) {
resolve(data)
} else {
reject(error)
}
})
But usually when dealing with async requests, the thing you are calling will often be returning a promise, so you can attach the then and catch callbacks there.
apiRequest(data)
.then((result) => {
// all good
})
.catch((err) => {
console.log(err)
})
const mock_api = () => new Promise((res, rej) => {
const number = Math.floor((Math.random() * 100) + 1);
setTimeout(() => {
if (number%2==0) return res('randomly RESOLVED')
return rej('randomly REJECTED')
}, 2000)
})
const async_promise = () => new Promise(async (resolve, reject) => {
try {
const resolvedPromise = await mock_api()
resolve(resolvedPromise)
} catch (e) {
reject(e)
}
})
const classicPromise = () => new Promise((resolve, reject) => {
mock_api()
.then(resolve)
.catch(reject)
})
const makeAsyncRequest = async () => {
try {
const data = await async_promise()
console.log('ASYNC AWAIT RESOLVE', data)
} catch (e) {
console.log('ASYNC AWAIT ERR', e)
}
}
makeAsyncRequest()
classicPromise()
.then(r => console.log('PROMISE CHAIN RESOLVE', r))
.catch(e => console.log('PROMISE CHAIN ERR', e))
Because of you resolve before reject so it cannot run into reject,
You can use:
if (printResult) {
resolve(printResult)
} else {
reject(console.log('Error'))
}
You can catch exceptions and return them as rejected Promises
function asyncFunc() {
try {
doSomethingSync();
return doSomethingAsync()
.then(result => {
ยทยทยท
});
} catch (err) {
return Promise.reject(err);
}
}
Always check for err if there is any err return a promise (example below)
// 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.parse(body));
}
})
})

Nested Promise with setTimeout

I have a nested promise. The promise resolves or rejects based on another promise resolving or rejecting with a setTimeout of 0 so as not to clog:
return new Promise((resolve, reject) => {
promiseInst
.then(value => {
executeSoon(() => {
dispatch({ ...action, status: "done", value: value });
resolve(value);
});
})
.catch(error => {
executeSoon(() => {
dispatch({
...action,
status: "error",
error: error.message || error
});
reject(error);
});
});
});
the executeSoon() is executeSoon(fn) { setTimeout(fn, 0); }
How do I simplify this? Tried to get rid of the outer promise wrapper and returning the inner promise directly but got stuck with the resolve and reject not being defined. So I thought I'd just return a Promise.resolve(value) from inside the .then and Promise.reject(error) from the catch, but this does not work either. I feel it might be possible to simplify this, but can't quite get my head around it.
Just use a promising timer:
const timer = ms => new Promise(res => setTimeout(res, ms));
Then its as simple as:
timer(0).then(() => promiseInst)
.then(...)
.catch(...)
.... but actually you dont need the timer as promises are guaranteed to resolve one tick after resolve() was called.
Remember that a then handler is always executed asychronously, there's no need for setTimeout(..., 0) in the normal case. So if the setTimeout doesn't have another purpose:
return promiseInst
.then(value => {
dispatch({ ...action, status: "done", value: value });
return value;
})
.catch(error => {
dispatch({ ...action, status: "error", error: error.message || error });
throw error;
});
If it does something important, I'd probably have a promise-enabled version, something along these lines:
const setTimeoutPromise = (delay = 0) => new Promise(resolve => {
setTimeout(resolve, delay);
});
Then see the lines with *** below:
return promiseInst
.then(value => setTimeoutPromise().then(() => value) // ***
.then(value => {
dispatch({ ...action, status: "done", value: value });
return value;
})
.catch(error => setTimeoutPromise().then(() => { // ***
dispatch({ ...action, status: "error", error: error.message || error });
throw error;
})); // <== *** Note one more )

general solution to retry a promise in javascript

I try to give out a general solution for retrying a promise. Below is my way and comes an error of "Uncaught (in promise)".
How can I fix this problem?
function tryAtMost(maxRetries, promise) {
let tries = maxRetries
return new Promise(function(resolve, reject) {
promise.then((result) => {
resolve(result)
})
.catch(err => {
if (tries > 0) {
console.log(`tries with ${tries}`)
tryAtMost(--tries, promise);
} else {
reject(err)
}
})
})
}
tryAtMost(3, promise).then(result => {
console.log(result)
})
.catch(err => {
console.log(err)
})
The reason for what you asked about is that you're missing a call to resolve in your catch:
.catch(err => {
if (tries > 0) {
console.log(`tries with ${tries}`);
resolve(tryAtMost(--tries, promise)); // <=== ****
}
else {
reject(err)
}
})
...and so you're creating a promise that is never handled by anything, and so if it rejects, you'll get an unhandled rejection.
But, tryAtMost has a problem: It cannot work with the information you've given it, because it doesn't know what to try. You need to pass it an executor, not a promise, because it's the work of the executor that you need to retry. This also makes the function a lot simpler:
function tryAtMost(tries, executor) {
--tries;
return new Promise(executor)
.catch(err => tries > 0 ? tryAtMost(tries, executor) : Promise.reject(err));
}
Use:
tryAtMost(4, (resolve, reject) => {
// The thing to (re)try
});
Example:
function tryAtMost(tries, executor) {
console.log(`trying, tries = ${tries}`);
--tries;
return new Promise(executor)
.catch(err => tries > 0 ? tryAtMost(tries, executor) : Promise.reject(err));
}
tryAtMost(4, (resolve, reject) => {
const val = Math.random();
if (val < 0.3) {
resolve(val);
} else {
reject(val);
}
})
.then(result => console.log(result))
.catch(err => console.error(err));

Extracting functions in a Promise chain

I am wanting to refactor a Promise chain by extracting out some functions. Currently I have
const getData = (uuid) => {
return new Promise((resolve) => {
fetch(
// go fetch stuff
)
.then((response) => {
if (!response.ok) {
return resolve(false);
}
return response;
})
.then(fetchres.json)
.then(response => {
// Do more stuff that requires resolves that I will also want to refactor
})
.catch(err => {
console.log(err);
resolve(false);
});
});
};
So I want to extract the part where I resolve the unsuccessful responses. But pass along any successful ones. I have pulled it out like so.
const resolveUnsuccessfulResponses = (response) => {
if (!response.ok) {
return response.resolve(false);
}
return response;
}
const getData = (uuid) => {
return new Promise((resolve) => {
fetch(
// go fetch stuff
)
.then(resolveUnsuccessfulResponses)
.then(fetchres.json)
.then(response => {
// Do more stuff that requires resolves that I will also want to refactor
})
.catch(err => {
console.log(err);
resolve(false);
});
});
};
Now I'm understandably getting the error resolve is not defined. How can I resolve this Promise in an external function?
Should I pass resolve to my extracted function? That would seem clunky.
.then(response => resolveUnsuccessfulResponses(response, resolve))
I might end up having something like
.then(fetchres.json)
.then(parseResponseData)
.then(postDataSomewhere)
.then(doOtherThings)
.then(doEvenMoreCoolThings)
And to have to pass response and resolve to each of them seems wrong
You should return a new Promise from your external functions aswell:
const resolveUnsuccessfulResponses = (response) => {
return new Promise((resolve, reject) => {
if (!response.ok) {
return resolve(false);
}
return resolve(response);
});
}

Categories

Resources