Nested Promise with setTimeout - javascript

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 )

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);
});

Rejecting a Promise with another new Promise

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);
});

Calling reject multiple times in the chain not being caught

I was expermenting with promises and error handling, but I cannot explain the behaviour of a piece of code. Promise.reject is called twice, the first is handled perfectly but the latter is not being caughed at all.
const a = Promise.resolve('test');
a
.then(item => Promise.reject('promise reject 1'))
.then(
(a) => {
console.log(a); // value: test
},
(err) => {
console.log(err); // value: promise reject 1
}
).then((a) => {
console.log('continue1'); // being called
Promise.reject('promise reject 2') // called but not caught
},
(err) => {
console.log(err); // never being called
})
.catch((err) => {
console.log(err); // never being called
});
I expected the catch to catch the error introduced at line 14 (Promise.reject('promise reject 2')), but the catch handler is never called
Promise.reject() just makes a rejected promise object. Your chain doesn't know anything about it unless you return it. If you return it, the next catch will catch it:
const a = Promise.resolve('test');
a
.then(item => Promise.reject('promise reject 1'))
.then(
(a) => {
console.log(a); // value: test
},
(err) => {
console.log(err); // value: promise reject 1
}
).then((a) => {
console.log('continue1'); // being called
return Promise.reject('promise reject 2') // << ---- Return me!
},
(err) => {
console.log(err); // never being called
})
.catch((err) => {
console.log("from catch:",err); // caught!
})
You can also throw in then():
const a = Promise.resolve('test');
a
.then(item => Promise.reject('promise reject 1'))
.then(
a => {
console.log(a); // value: test
},
err => {
console.log(err); // value: promise reject 1
})
.then(
a => {
console.log('continue1'); // being called
throw(new Error('promise reject 2')) // <-- no return required
},
err => {
console.log(err); // never being called
})
.catch(err => {
console.log("from catch:",err.message); // caught!
})

Promises can't run code after resolve/reject

I have async function in async function. In the second I must wait when promises resolve or reject and after run other code below. But if promise reject my code stopping and no run other functions. How I can fix it?
await axios.all(promises).then(res => {
axios.patch("/url", { foo: bar }).then(async () => {
const promises2 = arr.map(item => {
return axios.post("/url-2", item)
});
await Promise.all(promises2)
.then(() => console.log("resolved")) //this not calling ever
.catch(() => console.log("failed")) //this not calling ever
console.log("This console log ever not working")
})
})
Promises aren't chained properly, axios.patch(...) promise isn't returned. await is syntactic sugar for then and catch, its purpose is to get rid of nested functions where possible. It should be:
const res = await axios.all(promises)
await axios.patch("/url", { foo: bar })
const promises2 = arr.map(item => {
return axios.post("/url-2", item)
});
try {
await Promise.all(promises2)
console.log("resolved"))
} catch (err) {
console.log("failed");
}
The order of your code is wrong. Of course if the first promise is rejected, then the rest will not be called.
Try rewriting your code this way:
let res = await axios.all(promises).catch(() => { console.log("failed"); return false; });
if (!res) {
// Do something when rejected
....
}
// Call the 2nd promise
let res2 = await axios.path("/url", {foo: bar}).catch(() => {console.log("failed 2"); return false; });
if (!res2) {
// Do something when the 2nd promise is rejected
...
}
// Call your last promise
let res3 = await Promise.all(promises2).catch(() => {console.log("failed 3"); return false; });
if (!res3) {
// Do something if it is rejected again
....
}
// Otherwise, do your thing
Try this code, it should pinpoint where the error or rejection is occurring (i.e. it's definitely before Promise.all(promises2) is run
await axios.all(promises)
.then(res => axios.patch("/url", { foo: bar }), err => {
throw `all(promises) failed with ${err}`;
})
.then(() => {
const promises2 = arr.map(item => {
return axios.post("/url-2", item);
});
return Promise.all(promises2)
.then(() => console.log("resolved")) //this not calling ever
.catch(err => {
throw `all(promises2) failed with ${err}`;
});
}, err => {
throw `patch failed with ${err}`;
})
.catch(err => console.error(err));
Note I've removed async/await, because in the code you've posted it is totally unnecessary

Passing promises through functions React Native

I'm brand new to react native and I've been browsing through snippets of code and am confused as to how promises are passed along.
I have this event handler onRefresh() that is called when I pull down on a flatlist and I'm trying to have it use the return of apiSearchDB when it returns true/false.
onRefresh = () => {
this.setState({...}, () => {
return this.apiSearchDB()
.then(function(response) {
console.log(response);
})
.catch((error) => {
console.log(error);
});
})
}
apiSearchDB = () => {
return fetch('/some_endpoint')
.then((response) => response.json())
.then((json) => {
this.setState({
...
}, () => {return true})
return true;
}).catch((error) => {
console.error(error);
return false;
})
}
The line console.log(response); only prints undefined and I can't figure out why.
Could my handler also be written as
onSearch = () => {
return new Promise((resolve, reject) => {
var response = this.apiSearchDB();
response
? resolve();
: reject();
}
});
}
or onSearch = () => {...} and function onSearch(){...}?
Thank you in advance!
You should read more about using promises (good article - We have a problem with promises). However, two basic rules that will help you in this case are are:
The value returned from a promise is wrapped in a promise.
Promises can be chained.
The apiSearchDB should return a promise that contains the json as the resolved value, and error as the rejected value:
apiSearchDB = () =>
fetch('/some_endpoint')
.then((response) => response.json())
.then((json) => json)
// can be removed unless you want to do something with the error before passing it on
.catch((error) => Promise.reject(error));
The onRefresh (or onSearch) method should get the promise from apiSearchDB, and add it's own chain. Resolve promise should be handled with the then handler. If it's the rejected value, it will be handled by the catch handler:
onRefresh = () =>
this.apiSearchDB()
.then((response) => {
console.log(response);
// do something with response
this.setState({...}, () => {
});
return response;
})
.catch((error) => {
console.log(error);
// do something with error
this.setState({...}, () => {
});
});
}

Categories

Resources