Please indicate your availability here: http://doodle.com/poll/2iwihhwrw9tx8kkv.
I suggest we use Hangouts, but I'm open to other options.
@annevk which timezone?
@delapuente I configured the timezone so it should show up in your local timezone.
The meeting will take place 2017-01-24, 4PM (GMT+01:00). You can still attend, just let me know and I'll share the invite.
Tim O'Ryan, unfortunately I don't have your email address. Please contact me directly so I can add you to the meeting.
To be clear, that'd be 3 PM (15:00) UTC, and 7 AM Pacific time? (Also, to spare newcomers some counting: 2017-01-24 is Tuesday.)
Yes, I meant to include this: https://www.timeanddate.com/worldclock/fixedtime.html?msg=Fetch%20termination%20API%20%22meeting%22&iso=20170124T15&am=50. And again, if you want to attend I need to know.
Hey, I would be interested in attending if I'm invited. If I'm not that's also totally fine. I don't want to add in hours so I won't influence the meeting time - let me know when the time is set.
@benjamingr assuming I found the correct email address you got an invite. If not, you need to give me your email address. The time is set as per above.
Thanks! I'll do my best to attend.
Here's the stuff I'd like to get answers for:
fetch() provide means to control/observe the fetch?Use-cases to consider:
fetch(url).then(r => r.json()).fetchEvent.respondWith(fetch(fetchEvent.request)) - does this get me anything for free? If the page aborts the fetch, will the service worker request/response be aborted?var cancelController;
fetch("/fetch", {
cancel(cancelFn) { cancelController = cancelFn; }
});
cancelController(); // cancel, returns a promise with true/false
?
var cancelController;
fetch("/fetch", {
control(controller) { cancelController = controller; }
});
cancelController.cancel(); // cancel, returns a promise with true/false
const fetch = fetch("/fetch");
fetch.cancel(); // cancel, returns a promise with true/false
const readonly = fetch.then();
Other use cases to consider: it would be nice if this mechanism were generic enough to be reused for canceling a stream pipeTo as well.
We're looking for something that cancels the request, but also the response if it's in-flight. This means aborting the body stream if the response body is in-flight.
We're dismissing 'tokens' as an API. Although they work well for cancellation, they don't work well for other modifiers like "priority change".
Adding methods to the return value of fetch() feels too risky. The API gets pretty confusing. The 'species' could be a regular promise:
let fetchling = fetch(url);
// Works…
fetchling.cancel();
fetchling = fetch(url).then(r => r.json());
// Does not work, "cancel" is undefined.
fetchling.cancel();
Although this provides an easy way to return a regular promise, it's pretty confusing. If .then created a controllable fetch promise:
let fetchling = fetch(url).then(r => r.json());
// Works as expected:
fetchling.cancel();
fetchling = fetch(url).then(() => fetch(anotherURL));
// Only cancels the first fetch, which is weird:
fetchling.cancel();
const fetches = Promise.all([
fetch(url1),
fetch(url2),
fetch(url3)
]);
// Does not work, "cancel" is undefined
fetches.cancel();
That said, we're not against controlling methods being added to the return value in future.
We're going to move forward with the revealing-function pattern.
fetch(url, {
control(controller) {
// ...
}
});
Where controller will have methods that alter the in-progress fetch, including canceling & later changing priority.
There will be an component that allows the developer to observe the progress of the fetch. This includes changes to priority, progress, final state (complete, cancelled, error etc). This component will include async getters for current state.
The service worker will receive the "observable" component only.
The observable component should use addEventListener rather than observables. We don't want a TC39 dependency, and true observables are likely to be compatible with addEventListener. We should be careful with the naming of this observer as a result.
What does cancellation looks like? I'm pretty sure this will be a promise rejected with a DOMException with name 'AbortError', but we forgot to cover this in the call. It might already be assumed.
What's the link between the controller and observer? Does the controller object extend the observer? Does the controller have the observer as a property? Are the objects entirely separate?
What's the API for the controller/observer? This is the next step, and there have been some proposals already. Some loose requirements:
We're going to move forward with the revealing-function pattern.
@jakearchibald does this include passing the future FetchController object to the fetch()? I mean:
const control = new FetchController();
const fetching = fetch(request, { control });
@delapuente we need to hash out the details. If you have specific ideas for how it could all work well together, they're most welcome. A somewhat more detailed proposal by @stuartpb can be found at https://github.com/stuartpb/FetchController-spec.
@delapuente I updated the original post at https://github.com/whatwg/fetch/issues/447 with the current state of things.
If there'll be another meeting, I'd like to be included - some time between noon and 7 PM Pacific, if possible (or as close to that as would be feasible).
My feedback on the meeting notes:
addEventListener, and I think that's quite async enough. If this statement means to assert that multi-threading should imply all mutable properties to be only obtainable through asynchronous accessors, I will state now that I do not concur with that assertion, and can expand on the reasons in a separate issue.coll.forEach(ctl=>{/*...*/}) seems perfectly reasonable to me.observe.addEventListener('abort',e=>coll.forEach(ctl=>ctl.abort())) seems fine to me.@stuartpb thanks for the feedback. Just to clarify, when I wrote things like:
What's the link between the controller and observer?
I don't mean "we don't have a clue", I just mean it's yet to be decided. Your proposals have been read, and are being considered.
Closing this as the meeting happened. I've updated https://github.com/whatwg/fetch/issues/447 and discussion can continue there.
Most helpful comment
Summary
Decided
We're looking for something that cancels the request, but also the response if it's in-flight. This means aborting the body stream if the response body is in-flight.
We're dismissing 'tokens' as an API. Although they work well for cancellation, they don't work well for other modifiers like "priority change".
Adding methods to the return value of
fetch()feels too risky. The API gets pretty confusing. The 'species' could be a regular promise:Although this provides an easy way to return a regular promise, it's pretty confusing. If
.thencreated a controllable fetch promise:That said, we're not against controlling methods being added to the return value in future.
We're going to move forward with the revealing-function pattern.
Where
controllerwill have methods that alter the in-progress fetch, including canceling & later changing priority.There will be an component that allows the developer to observe the progress of the fetch. This includes changes to priority, progress, final state (complete, cancelled, error etc). This component will include async getters for current state.
The service worker will receive the "observable" component only.
The observable component should use
addEventListenerrather than observables. We don't want a TC39 dependency, and true observables are likely to be compatible withaddEventListener. We should be careful with the naming of this observer as a result.Less-decided
What does cancellation looks like? I'm pretty sure this will be a promise rejected with a DOMException with name 'AbortError', but we forgot to cover this in the call. It might already be assumed.
What's the link between the controller and observer? Does the controller object extend the observer? Does the controller have the observer as a property? Are the objects entirely separate?
What's the API for the controller/observer? This is the next step, and there have been some proposals already. Some loose requirements: