My function could return a promise or value, how to avoid it? [duplicate] - node.js

This question already has answers here:
How to maintain a promise-like API in this case?
(2 answers)
Closed 6 years ago.
I think it's bad practice to have different return types. So, this is my function, and I want it to always return a promise.
I tried to simplify the scenario. Let's say I have two lines of products (line X and line Y) and the way I'm retrieving a product by name, from each line is totally different from the other.
Please also note that ideally, I wanted to have a function to "or" two promises and return whichever that resolves successfully. But I couldn't think of a better way to achieve this!
ProductService.findProductByName = function findProductByName(name) {
return LineXService.findOneByName(name) // promise
.then(function _returnProduct(product) {
return product
? product // value
: LineYService.findOneByName(name)); // promise
})
};

You're right that returning a consistent thing is better than an ambiguous result. Normally you can cast an arbitrary value into a promise easily enough. For example using resolve:
if (product) {
return Promise.resolve(product);
}
return LineYService.findOneByName(name);
It's worth noting, as Kevin B observes, that this is irrelevant in this particular case since your outer function always returns a promise. The need to promisify a value is only a concern if this is not part of a surrounding promise.

Related

Replacing Unwrap()s with ? - compiler complaining on functions that do return Result or Option [duplicate]

This question already has answers here:
What is this question mark operator about?
(4 answers)
Why do try!() and ? not compile when used in a function that doesn't return Option or Result?
(4 answers)
the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `std::ops::Try`)
(1 answer)
What is the idiomatic way to handle/unwrap nested Result types?
(2 answers)
Closed 7 months ago.
The community reviewed whether to reopen this question 7 months ago and left it closed:
Original close reason(s) were not resolved
I'm only a few days into my Rust journey and going over my now functionally completed first project, working on exercising unwrap()s from my code.
The first two instances I've tried, I've completely failed and I cannot work out why. I have this line in my code:
let json = str::from_utf8(&buf).unwrap();
from_utf8 returns Result<&str, Utf8Error>, but trying:
let json = str::from_utf8(&buf)?;
Has a compiler error of "This function should return Result or Option to accept ?", but it does return Result. I can only assume that the pointer & is having an effect here?
I've refactored this now to:
match str::from_utf8(&buf) {
Ok(json) => {
let msg: MyMessage = serde_json::from_str(json).unwrap();
self.tx.try_send((msg, src)).expect("Could not send data");
}
Err(e) => {}
};
I still need to work out what to do in the Err but I've gotten rid of the unwrap() call. However, there's another.
serde_json::from_str(json).unwrap();
This returns Result<T>, so:
serde_json::from_str(json)?;
This is also complaining about the fact it should return Result when it already does.
At this point, it's safe to assuming I'm really confused and I don't understand half as much as a thought I did.
Countless blogs just say use ?, yet, in every instances I think it should work and the return types appear suitable, the compiler says no.
Would the From trait work here? Is it common to have to write traits like this?
from_utf8 returns Result<&str, Utf8Error>, but trying:
let json = str::from_utf8(&buf)?;
Has a compiler error of This function should return Result or Option to accept ?. But it does return Result.
This function here refers to the outer function. That is, the function you are writing, not from_utf8.
? will return an error from your function if there was one, thus your function needs the right return type to be able to return an error.
Because from_utf8 is not the source of the issue, you'd get the same error like this too:
let r = Err(...);
let json = r?;
The ? operator is roughly equivalent to a match with an early return for the error case, so in your example
fn foo() {
let json = str::from_utf8(&buf)?;
// ...
}
is roughly equivalent to
fn foo() {
let json = match str::from_utf8(&buf) {
Ok(j) => j,
Err(e) => return Err(e.into()),
}
// ...
}
This should make it clear where the error is coming from. You are trying to return a Result from a function that doesn't return anything.

Getting children of an element in Puppeteer: element.children.length works but element.children returns undefined

I have this code snippet:
const historicalDataTable = await findElementByClass(
"table",
elementClass,
page
); // This is a custom function I wrote. Works as expected.
const tableBody = await historicalDataTable.$eval(
"tbody",
(el) => el.children.length
);
console.log(tableBody);
This works as expected and returns the correct amount of children. However when I do
const tableBody = await historicalDataTable.$eval(
"tbody",
(el) => el.children
);
And remove the length, it returns undefined. What is going on here?
el.children (Element#children) will yield an HTMLCollection which is not serializable and can't be marshalled from the page's execution context into yours, so evaluate returns undefined instead.
Now, this isn't fully obvious when looking at the elementHandle.$eval docs as the only indication is that the return value is <Promise<Serializable>>, but it becomes clear from the executionContext.evaluate docs:
returns: <Promise<Serializable>> Promise which resolves to the return value of pageFunction
[...]
If the function passed to the executionContext.evaluate returns a non-Serializable value, then executionContext.evaluate resolves to undefined. DevTools Protocol also supports transferring some additional values that are not serializable by JSON: -0, NaN, Infinity, -Infinity, and bigint literals.
(Emphasis mine.)
el.children.length (HTMLCollection#length) on the other hand is a simple number which is serializable.
You have to do whatever you want to do with those elements inside of your pageFunction and return only some serializable value.
Alternatively, you could also use elementHandle.evaluateHandle to return a JSHandle to the HTMLCollection and use that handle later in another call to an evaluate-type function. (Note that that would be the only thing you can do with it though. You couldn't access .length for example from your own execution context, only from another pageFunction1.)
1: This is not entirely true, since you could for example use jsHandle.getProperty to get another JSHandle for the length, followed by jsHandle.jsonValue to get the value as number - but both of these operations are asynchronous and probably it's a lot more efficient to write your code in such a way that you can handle all the necessary operations inside the page's execution context in the first place, without too many context switches.

mongo db virtual get function how to return document

details:mongodb,mongoose,nodejs
example :
schema.virtual(''name').get(function() => {
return this.anything;
})
how the this key work to point document?
Is get method return document?
Might be a typo in the post but your string starts with two quotes.
You are mixing up the syntax for regular functions and arrow functions.
Do this:
schema.virtual('name').get(function() {
return this.anything;
});
You cannot use an arrow function in this situation anyway since arrow functions do not allow the rebinding of the this context.

Using chain validation to check existence of optional fields with Express Validator

I am trying to check for the existence of an optional field in an API request, and if that field exists, perform a nested validation to check if two other fields (one or the other, or implicitly both) exist inside of it. I am using Express Validator to try and accomplish this task.
// Sample request body
{
<...>
thresholds: {
min: 3,
max: 5
}
}
// (Attempted) validation chain
check('thresholds').optional()
.custom( innerBody => {
console.log('THRESHOLDS', innerBody);
oneOf([
check('innerBody.min').optional(),
check('innerBody.max').optional()
]);
})
The above snippet is part of a larger validation chain I'm validating the full request body on. I also tried removing the innerBody. string from the inner checks but still no luck. I am console.loging the threshold body, and it prints out correctly, however I still get a validation error, when I'm trying to get my integration test to pass:
{"name":"ValidationError","message":"ValidationError: Validation failed","errors":[{"location":"body","param":"thresholds","value":{"min":3,"max":5},"msg":"Invalid value"}]}
I am relatively new to Express Validator so if I'm chaining the validation wrong/not using oneOf correctly or something would love some pointers!
Thanks
Looks like the .custom function needs to return a Promise. Answer below:
.custom(innerBody => {
if (!(innerBody.min) || !(innerBody.max)) return Promise.reject('Missing min or max');
return Promise.resolve();
})
Remember: Always return a boolean value from the callback of .custom()
function. Otherwise your validation might not work as desired.
Source: Custom validation guide
In general, you might have needs in use of Promises if you deal with asynchronous .custom() function. Then you'll be obligated to return Promise.resolve() / Promise.reject() for correct validator behaviour.
Source: SO answer

Making Mongoose/MongoDB query helper plugin return zero results

I'm developing a Mongoose Query Helper plugin that provides the chainable method .search(query). On certain conditions, I want the query to return zero results, no matter how the other methods in the query builder chain behave. Turns out this isn't so easy as I have assumed.
Basically, I have the following code:
schema.query.search = function search(query) {
if ("query is invalid") {
// return no results => no easy way to achieve that?
}
return this.find(query);
};
Now, I want SomeModel.find({}).search(someQuery).exec() to return no results in case the query is invalid. I first tried to return this.limit(0), but turns out a limit of 0 is equivalent to setting no limit.
As a temporary solution, I do return this.find({ nonExistingField: 'something' }) which always results in no results, but this does seem a bit awkward and is probably also not so optimal in terms of performance as it triggers a search when no search is needed.
Thanks in advance for your help!

Resources