Skip to content

play() should return a Promise resolved when the request succeeds/fails #505

Closed

Description

@mounirlamouri

/cc @jernoble @padenot @foolip

At the moment, one has to call play() and check for errors in various places to know if the request failed. Also, when a play() call is blocked because the UA doesn't allow it for some reasons (no user gesture, page not visible, etc.), it is very hard for the page to know about it because it is not a MediaError. The common way for a page to find out the UA blocked a play() request is the absence of playback. It is not an ideal developer experience.

I would like to have play() return a Promise<> so one can do:

media.play().then(function() {
  // playback started
}, function(e) {
  // playback failed, use 'e' to check why
});

(Note that when we resolve the promise might have issues similar to #309.)

After talking with @foolip about this, we think it would be great to use DOMException instead of MediaError when rejecting the play promise. It would be a first step in order to deprecate MediaError in order to use DOMException.

I suggest that we have this correspondence table:

MediaError DOMException
MEDIA_ERR_ABORTED "AbortError"
MEDIA_ERR_NETWORK "NetworkError"
MEDIA_ERR_DECODE "EncodingError"
MEDIA_ERR_SRC_NOT_SUPPORTED "NotSupportedError"

Then, we can add "NotAllowedError" to be used if the play() request is rejected by the UA because it is not currently allowed by the UA or the system. We didn't find a matching error in the current list of DOMException. However, it's fine to create new names so unless someone has a better idea, I think it should be fine to use this one.

WDYT?

Activity

  1. domenic commented on Jan 12, 2016

    @domenic
    Member

    I love it, of course :). Using DOMException is a nice touch as well. Do you hope to fix #309 at the same time? I don't 100% understand the timing issue, but it sounds like @foolip does, so we're probably covered there...

  2. padenot commented on Jan 12, 2016

    @padenot

    @cpearce, we were discussing this with @mounirlamouri the other day, do you have comments on this API ? We thought it would be useful for cases where playback has been denied, for example.

  3. jernoble commented on Jan 12, 2016

    @jernoble

    I like it as well. We were considering adding a diagnostic console log so authors could discover why their play() requests failed, but this is better.

  4. cpearce commented on Jan 13, 2016

    @cpearce

    I like think it's a great idea. We were also considering adding webconsole logging to identify the reasons for load failures, but this is much better.

    I'd also like to see load() return a promise. It would be good if seeking could too, but obviously we'd need to add an explicit seek(time) method rather than seeking via setting currentTime.

  5. added a commit that references this issue on Feb 1, 2016
    be8edde
  6. foolip commented on Feb 1, 2016

    @foolip
    Member

    The promise-vending play() is now live in the spec, so for everyone who did not follow along in the pull request, here's a summary.

    Every call to play() returns a promise, which will be resolved at the same time that the playing event is fired. If we were already playing, the promise will be resolved with the same timing, but without first firing a playing event.

    There are two ways for play() to return an already-rejected promise, and that is "if the user agent or the system does not allow media playback in the current context" (mobile autoplay blocking) and if the resource selection algorithm has already failed with MEDIA_ERR_SRC_NOT_SUPPORTED, as playback cannot succeed without loading another resource.

    The promise rejections that happen outside the play() method are more complicated. There are ways for the promise to be left unsettled when it seems like we should be able to reject it, specifically in the case of network and decode errors. In #509 (comment) and #509 (comment) I say some uncharitable things about how error handling currently works. If left unsettled, promises will be rejected on the next pause of invocation of the media element load algorithm.

    Known issues that would improve upon the current spec:

    Finally, for everyone who likes promises, there are also issues for promisifying pause(), load() and a new seek().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions