How to reject the promise from the _.each loop, it is never reaching document.write('Failed');. Are there any better functions in lodash to handle this situation.
function check(){
return Promise
.all(
[
Promise.resolve([1,3,4]),
Promise.resolve([0,4,3]),
Promise.resolve(undefined)
]).then(function(results){
return _.each(results, function(result){
return _.each(result, function(value) {
// should reject when value is 0
if(!value){
return Promise.reject();
}
});
});
});
}
check().then(function(){
document.write('All Success');
}, function(){
// Never reaching this code.. :(
document.write('Failed');
});
Here is the plnkr.co link
There's no reason to create a new promise in the then callback and return it. The point of promises is to allow you to write asynchronous code in a more 'synchronous-like' way. What you want to do in your then callback is to throw an error:
function check(){
return Promise
.all(
[
Promise.resolve([1,3,4]),
Promise.resolve([0,4,3]),
Promise.resolve(undefined)
]).then(function(results){
return _.each(results, function(result){
return _.each(result, function(value) {
// should reject when value is 0
if(!value){
throw new Error();
}
});
});
});
}
check().then(function(){
document.write('All Success');
}, function(){
// Never reaching this code.. :(
document.write('Failed');
});
This will cause a rejection in the promise chain.
The _.each() function returns the list in the first parameter and cannot be broken out of, according to the documentation.
To achieve what you want, try using the for...of loop as documented here:
function check(){
return Promise
.all(
[
Promise.resolve([1,3,4]),
Promise.resolve([0,4,3]),
Promise.resolve(undefined)
]).then(function(results){
for (let result of results) {
for (let value of result) {
// should reject when value is 0
if(!value){
return Promise.reject();
}
});
});
});
}
check().then(function(){
document.write('All Success');
}, function(){
// Never reaching this code.. :(
document.write('Failed');
});
If you insist on using the _.each() loop you will never be able to break out of the loop when it hits the first rejection, so I wouldn't recommend that approach. However, you could declare a variable just before the first loop that initially contains a resolved promise, replace it with a rejected promise if the !value check passes and then return this variable after the loop at the end of the final then().
You could use Promise.all again, combined with flatten and map
function check(){
return Promise
.all(
[
Promise.resolve([1,3,4]),
Promise.resolve([0,4,3]),
Promise.resolve(undefined)
]).then(function(results){
return Promise.all(_(results).flatten().map(result => {
if(result === 0) return Promise.reject()
}))
});
}
check().then(function(){
document.write('All Success');
//lert("all success");
}, function(){
document.write('Failed');
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.2/lodash.js"></script>
Also you could use some
function(results){
return Promise.all(results.map(result => {
if([].concat(result).some(value => value === 0)) {
return Promise.reject()
}
}
Related
I'm learning JavaScript promises and then, and am confused with this error using Node.js.
I would like dostart() to wait until nonblocking sleep is finished, and then return "Resolved" to the main function when it is done.
I get this error:
dostart().then(value => {
---------^
TypeError: Cannot read properties of undefined (reading 'then')
Help appreciated :)
function nonBlockingSleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function dostart() {
console.log("Hello2");
nonBlockingSleep(2000).then(() => {
console.log("Done");
return Promise.resolve("Resolved");
});
}
dostart().then(value => {
// main function - I'd like console.log to show "Resolved" when dostart() is finished
console.log(value);
})
dostart isn't async and doesn't return the promise from then, so you can't try to consume that promise where you call it.
You have at least a couple of options.
The simple one in this particular case is to return the promise from then:
function nonBlockingSleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function dostart() {
console.log("Hello2");
// *** Return the promise
return nonBlockingSleep(2000).then(() => {
console.log("Done");
// *** There's no need for `Promise.resolve` here, `then`
// _always_ returns a promise, and will use the return value
// here to fulfill it. (If you return a promise instead, it will
// resolve its promise to the promise you return instead of
// fulfilling its promise.)
return "Fulfilled";
});
}
dostart().then((value) => {
console.log(value);
});
Your other option is to use async/await:
function nonBlockingSleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
// *** Make `dostart` an `async` function
async function dostart() {
console.log("Hello2");
// *** `await` the promise from `nonBlockingSleep`
await nonBlockingSleep(2000);
console.log("Done");
// *** Return the fulfillment value for this function's promise
return "Fulfilled";
}
dostart().then((value) => {
console.log(value);
});
Side note: I changed "Resolved" to "Fulfilled" because we're fulfilling the promise in that particular case. It's common, but incorrect, to use "resolve" for "fulfill." It's true that fulfilling a promise resolves it, but the converse isn't true — resolving a promise doesn't always fulfill it. It might leave it pending, or even eventually reject it, if you resolve it to another promise. I've written up promise terminology in this blog post.
since dostart returns nothing you can fix it like this:
function dostart() {
console.log("Hello2");
return nonBlockingSleep(2000).then(() => { console.log("Done"); return Promise.resolve("Resolved"); });
}
or use keyword async
async function dostart() {
console.log("Hello2");
return await nonBlockingSleep(2000).then(() => { console.log("Done"); return Promise.resolve("Resolved"); });
}
I have some code where a function (which contains a promise) runs and then returns a boolean value. I then check to see if that value is true, and if so run some other code. I had the values logging to the console to do some debugging, and I noticed that the if statement that checks to see if the function returned true was running before the function even returned anything.
I have attempted to use "await" and "async" but I haven't found any success in using them.
javascript
function myFunc()
promise()
.then(value => {
console.log('Returned true');
return true;
})
.catch(err => {
console.log('Error', err);
});
end
if (myFunc()) {
console.log('Value was true');
} else {
console.log('Value was false');
}
Expected:
Returned true
Value was true
Actual:
Value was false
Returned true
You are trying to return a promise from inside your function, in the moment you use promises you are working with async code. That means that in order to get the value from the promise, the promise needs to be fulfilled first.
In your case you are evaluating the return value of your function, not the returned value of the promise. Since you do not have an explicit return in your function, it is returning undefined. That is why you see value was false in the console. Then your promise gets fulfilled and you see Returned true in the console, but you never evaluated that value return by the promise.
Supposing that you are invoking your function from the global scope you will need to use .then syntax to get access to the value returned by your promise.
So if your function is something like this:
function myFunc() {
return Promise.resolve()
.then(value => {
console.log('Returned true');
return true;
})
}
Your if statement should turn into something like this:
myFunc().then(value => {
if(value) console.log('It is true')
else console.log('Is it false')
})
Basically you wait for your promise to be fulfilled and when that happens you get the return value by param (in this simple example it is always true but it could be false as well).
I hope this helps you.
Try returning the promise from the function:
function myFunc()
return promise()
.then(value => {
console.log('Returned true');
return true;
})
.catch(err => {
console.log('Error', err);
});
end
if (myFunc()) {
console.log('Value was true');
} else {
console.log('Value was false');
}
This is not the best practice, I would stick with a good old promise chain:
promise()
.then(value => {
if (value) {
console.log('Value was true');
} else {
console.log('Value was false');
}
})
.catch(err => {
console.log('Error', err);
});
You need to use "await" to wait the promise response
promise = () => new Promise( (resolve, reject ) => resolve(true) );
async function myFunc(){
try {
let value = await promise();
if (value === true){
console.log('Returned true');
return true;
}
} catch (err) {
console.log('Error', err);
}
}
async function main(){
if ( await myFunc() ) {
console.log('Value was true');
} else {
console.log('Value was false');
}
}
main();
Javascript code, trying to resolve a promise immediately:
var promiseData;
var promise = <<<promise maker>>>.then(function (myContent) {
console.log("success");
}, function () {
console.log("fail!");
});
Promise.resolve(promise)
console.log("about to return");
return promiseData;
which output's to the console:
about to return
success
I have a requirement to make the promise return immediately (the promise is being created in a callback method, and the method needs to return a value immediately, returning the data later means we are no longer in the correct context and the value (that has not yet been returned) has already been used (as undefined).
Any suggestions of what I might be doing wrong?
Update:
<<<promise maker>>> is a call to a dependency that returns a promise;
It looks like you expect Promise.resolve(promise) to immediately halt, wait until the promise is resolved, and continue afterwards. That would come close to synchronous execution.
However, Promise.resolve(value) returns a Promise that immediately resolves with value, it does not resolve an existing Promise.
What you're looking for is await (or just Promise.then):
var promise = <<<promise maker>>>.then(function (myContent) {
console.log("success");
}, function () {
console.log("fail!");
});
promise.then(function() {
console.log("about to return");
});
You might observe that I left out the promiseData in the snippet. That's because in order to return the data at the right moment, you have to be asynchronous there as well. So you have to actually return a Promise that will resolve with promiseData, it comes down to:
<<<promise maker>>>
.then(function(promiseData) {
console.log('success');
return promiseData;
})
.then(function(promiseData) {
console.log('about to return');
return promiseData;
})
.catch(function(err) { console.log('fail!'); })
If I am not wrong, this function flow is near what you need, but it also returns a promise resolved into promiseData:
async function getPromiseData() {
try {
const promiseData = await <<<promise maker>>>;
console.log("success");
console.log("about to return");
return promiseData;
} catch (err) {
console.log("fail!");
}
}
In the following snippet, lineReader listens to an event line. When a line event is received, it calls da on Parser which returns a Promise
lineReader.on('line',(line) => {
Parser.da(line).then((info) => {
});
});
lineReader.on('close',() => {
req.end();
});
Parser.da = function(line) {
return new Promise((resolve,reject) => {
geo.getLocation().then((r) => {
console.log(r); return resolve(r);
});
});
}
da function in return calls a function which also operates on Promise. What happens is that I can never see the output from geo.getLocation and readLine.on('close') gets called.
What should be the way to handle this situation?
You are not resolving the promise. When you get the result from geo service you need to resolve the data.
Take a look this
Parser.da = function(line) {
return new Promise((resolve,reject) => {
geo.getLocation().then((r) => {
console.log(r);
resolve(r);
});
});
}
Why do you not just return the Promise from geo.geoLocation() instead of wrapping it into another promise? Like this:
Parser.da = function(line) {
return geo.geoLocation();
}
Or you might want to chain "then"'s instead. Although this is synchronous
Parser.da = function(line) {
return geo.geoLocation().then(function (r) {
console.log(r);
return r; // return r to chain it to the next ".then"
});
}
One possible problem might be that a promise is asynchronous so the lineReader.on("line"); event is closed before the promise can be executed because the event is synchronous. And then the lineReader.on("close"); is executed before the promise is resolved.
Also you should always have a "catch" in your promise so you can see if there are any errors. Like this:
lineReader.on('line',(line) => {
Parser.da(line).then((info) => {
// ...do code here
}, console.error); // errors will be outputted to console
});
I'm using bluebird in node with express ,when I return res.end(),Promise still goes to the next chain,here's my code:
Promise.resolve(operate).then(function(data){
if (!!data && data.length !=0) {
log.info('success');
return true;
}else {
log.warn('fail');
return res.end();
}
}).then(function(data){
if(data) {
log.info('done');
return res.end();
}else {
log.warn('fail');
return res.end();
}
})
And I got 2 'fail' in the log if it's failed,how can i make it stop if i got 'fail' in the first time?Thank you!
bluebird version:~2.10.2;
node: 4.3.1;
express:~4.2.0
You can return either an error or a rejected promise instead of res.end. This will skip all success handlers until the end of the promise chain (technically until the first rejection handler):
Promise.resolve()
.then(() => Promise.reject())
.then(
() => console.log('this does not run'), // <-- success handler
() => console.log('this runs') // <-- rejection handler
);
So in your code:
Promise.resolve(operate).then(function(data){
if (!!data && data.length !=0) {
log.info('success');
return true;
} else {
log.warn('fail');
res.end();
return Promise.reject(/* optionally pass an error */); // <--- return rejected promise
}
}).then(function(data){
// this won't run if previous promise rejects
})
By definition the then method always return a Promise, so the chain is going to continue.
As it has been already pointed out you could reject the promise instead and catch it afterwards. If the error handling is the same in all cases you can use a catch at the end of the chain (putting a catch at the end is considered a good practice anyway).
Promise.resolve(operate).then(function(data){
if (!!data && data.length !=0) {
log.info('success');
return true;
} else {
return Promise.reject('fail');
}
})
.then(function(data) {
// true is being returned above so it will enter here always
// I guessed something instead of true could come here
if(data) {
log.info('done');
return res.end();
} else {
return Promise.reject('fail');
}
})
.catch(function(err) {
log.warn(err);
return res.end();
});
In this case returing a rejected Promise seems legit, but depending on the situation returning a rejected Promise to escape of the Promise chain could not be recommended because it can be mixed with a real rejection. In those case restructuring your chain could be the best option.