Monads are a particular pattern for function chaining. In OO terminology it is more like an interface than an object, so I would prefer to say that an object
support a monad pattern rather than an object
is a monad.
JS promises also supports chaining, but not in the same way as the monad pattern.
The Array.flatMap() method implements the monad pattern. The signature (in pseudo-typescript notation) would be:
Array<T>.flatMap(T => Array<T>): Array<T>
I.e the argument is a higher order function which return the same type, and the function also return the same type. This gives unique flexibility in chaining functions, because this:
[1, 2, 3].flatMap(x => [x + 1]).flatMap(x => x < 4 ? [x] : [])
has the same result as this:
[1, 2, 3].flatMap(x => [x + 1].flatMap(x => x < 4 ? [x] : []))
So the functions can be chained
or nested, arbitrarily, without affecting the result.
The above is equivalent to:
[1,2,3].map(x => x + 1).filter(x => x < 4)
Which also use method chaining, but not in the same flexible way - you cannot change the chaining to nesting and still get the same result. So not every form of method chaining conform to the monad pattern. (For better or worse - map/filter is clearly easier to read and write, just not as composable.)
Note that the definition of monad says nothing about what the semantics of the chaining method (flatMap() in this case) actually is. It only defines the rules for how they can be chained.
Generalized, the signature is:
Foo<T>.bind(T => Foo<T>): Foo<T>
(The method can be called anything, as long as it support the pattern. Traditionally it is called "bind".)
As far as I know, promises does not support a similar interface.