1) The browser guarantees that the Promises resolve in order, and that even if all the Promises use the same ArrayBufferView, inside the promise's resolve callback, the data is the correct value with respect to the OpenGL command stream at the time that iteration of getBufferSubDataAsync was called. Multiple frames can be queued up without needing separate destination ArrayBufferViews. The polling-based API requires a new ArrayBufferView for each readback, if the application expects to have multiple frames in flight.
2) It still requires allocation of an object (a WebGLSync) -- no way around that.