My promises are just the platform promises. The only abstraction introduced is in the catch function error handling to allow proper error matching. It’s as low as it can get binding wise.
Tasks are an extra abstraction around async operations with more directed control flow and (depending on the library) more possibilities to process async results. Task controlled async operations may be type-safer and less prone to runtime errors, but you need to wrap things and do some extra work, especially in a binding situation.
Considering the complexities of JS apps (and libraries), and the weird usage of promises in code I don’t control, I concluded that keeping it bare bone and just keep on using promises is easier for me.
I see async/await in JS more-or-less a tool to streamline the flow of Promises.
In such perspective, we verify the places await can prepended to–an expression of a Promise type.
Thus in the second example, p is just an int and cannot be awaited.
The current 10.1.0-alpha.2 npm release (as well as master) introduces a warning whenever nested promises are used, as this is known to introduce unsoundness. See discussion at the top of this thread.
There are alternative promise implementations that get around the problem by giving a special representation for nested promises.
In this exploration https://github.com/rescript-lang/rescript-compiler/issues/5707 a different approach is taken where it seems that one can safely type promises without using any special runtime representation. This is work in progress, the investigation is only semi-formal, but seems to work just fine on the problematic examples.
let getData = async (url: string) => {
let respones = await Fetch.fetch(url) // I have error here
->then(Fetch.Response.arrayBuffer)
// do any thing with respones
}
let respones = await fetch("").then(respones => respones)
This should work. We’d have to see where that then function is actually coming from, but the problem right now looks like it is that then is designed to continue a promise chain, so then is expecting you to return a new promise. You probably want thenResolve (if you’re using the new promise bindings).
This example code compiles and does what you’d expect:
type person = {name: string}
@val
external fetchData: unit => promise<person> = "fetch"
let fn = async () => {
let personName = await fetchData()->Promise.thenResolve(person => person.name)
personName
}