Fail Fast principle says you should fail as soon as possible for robust debugging. It is provides quicker feedback to a user if they have messed up. This goes against the "Constructors should do nothing" principle.
The good thing about Software Engineering principles is that there are so many to choose from. :-)
Imagine that your application asks for a Cake URL. Version A checks the URL as soon as possible. Version B waits and does no error checking. Both then ask for your name, the date you baked the cake, a review of the cake, and walk you through the special offer to receive 3 free issues of "Cake Monthly". So far, so good.
Finally, Version B does error checking and notices that the URL isn't a cake.
Maybe the user mis-typed, selected the wrong picture, or the code that dealt with that input has a bug and added a leading "http:" when it was already in the URL. Or maybe it is a cake and the network call is down.
1) Which would be easier to debug?
Version A should have a very clear stack trace pointing to
myUrlHTTPAdder() as a recent call that perhaps did something wrong. Version B will have a flaky URL and something about a magazine.
2) Which will retain more users?
I'll let you decide.
That said, doing an async network call in a constructor is a bit much.
One approach might be to have a
Boolean isValidatedCakeImage field, or a method
CakeImage getValidatedCakeImage(), which returns a Promise or a Future or whatever depending on your language. (Or maybe just a null and some method of polling or waiting).
At some point in the process your code calls that and takes the async hit. These methods could be mocked for testing.
A good question is whether the constructor launches the validation, or a later method. Good arguments for both sides here. Mainly, I don't think that "constructors shouldn't do nothing" should guide your decision here. Lean towards "Fail Fast" as your default, and back away if that doesn't fit the complexities.