-
-
Notifications
You must be signed in to change notification settings - Fork 88
Promise aware headers #319
Comments
That is pretty interesting... Hadn't thought about it much but I could see the value. If someone needed this feature and wanted to make a PR, I would be happy to review and accept a PR to that effect. |
Just ran into this myself. I tried using async: headers: computed(async function() { // (proof-of-concept)
const headers = {};
const token = await store.restore(); // (pseudocode)
if (token) {
headers.Authentication = `Bearer ${token}`;
}
return headers;
}) It appeared to work, but basically had no effect at runtime. Likely due to it not being promise-aware. I ended up using So 👍 (both to @alexlafroscia for unknowingly fixing my problem 😄, and to this issue) |
Hey @joeyespo, nice to see you! Just to play devil's advocate a bit, and to explore a solution that doesn't involve making the Header creation async, would an // app/services/session.js
import Service from '@ember/service';
import { task } from 'ember-concurrency';
export default Service.extend({
userToken: undefined,
authenticateUser: task(function* () {
const token = yield doSomeAsyncActionToGetTheToken();
this.set('userToken', token);
})
});
// app/service/ajax.js
import AJAXService from 'ember-ajax/services/ajax';
import { inject as service } from '@ember/service';
export default AJAXService.extend({
session: service(),
headers: computed('session.userToken', function() {
return {
token: this.get('session.userToken')
};
})
}); This way, you explicitly handle the asynchrony by being able to look at This ends up being better, both here and in other areas of Ember, since Ember's KVO doesn't really handle promises that well (and in the cases where it does through an |
You could bind to function*() {
return doSomeAsyncActionToGetTheToken();
} That's a bit cleaner; it'll be function*() {
return yield doSomeAsyncActionToGetTheToken();
} (although I find using both function*() {
const token = yield doSomeAsyncActionToGetTheToken();
return token;
} Note, if you try it out: something has to explicitly call |
Yes, you could solve this outside ember-ajax. There are parts of Ember Data that are promise-aware too, although it could also be sync with async handling outside the framework. My view is that if some parts of an API may be used in both sync/async, it's nice if it can handle both. I think it would be great if we could support an async |
I'm actually thinking about coming up with a pattern that we could extend to other properties like What do you think about creating a pattern where each property could be defined by either a property or method following the pattern We could then extend this pattern to |
To be clear, I'm definitely not against the idea of being able to set them asynchronously. I just don't want to open the door to the I'm going to get on a plane pretty soon, so I'll put a demo together of my idea around being able set properties sync or async and make a PR that we can look at together. |
If I understand you correctly, ember-ajax would look for Enjoy! |
Yup! Exactly. And I didn't get a chance to experiment with this on the plane, but will get something together by next week. |
@sandstrom As a user of |
Hmm... I want to rewrite with I'm thinking that this will actually require a import { getXHR } from 'ember-ajax';
const promise = this.get('ajax').request('/foo');
const xhr = getXHR(promise);
// or
const promise = this.get('ajax').request('/foo').then(response => response);
const xhr = getXHR(promise); something where you pass the promise (or child promise) in and get an XHR back, rather than accessing a property that we need to propagate through the custom promises. |
I don't mind We should try to avoid an extra call to dig out the xhr. Would it be possible to move from RSVP to native promises? That would solve the await issue without introducing a Also, have you considered dropping jQuery from It would be a good idea to make both changes in one swoop, since removing jQuery will touch a lof the promise internals anyway + it's a breaking change (although minor, but afaik it will affect the options hash). |
I think the problem isn't RSVP vs Promise, but rather that we have to make a sub-class that overrides
The whole idea is to be a wrapper for To re-write to use |
Ah, you may be right! ( was just guessing it was because of the RSVP) I see, I always thought the plan was to move this addon off jQuery. But in that case I'll see if we can switch over to native/polyfilled fetch or That way this addon won't need to see much churn or breaking changes, which is probably ideal for people wanting to use jQuery.ajax. And others can use |
Nope, I don't think so. Out of curiosity, what would that look like? I personally believe that |
Additions: - Makes the `options` method async, so that dependent properties can also be async (like `headers`) - Establishes a pattern that can be used for either defining properties synchronously through a property (or computed property) or asynchronously through a method that follows a specific naming convention Problems: - `async/await` breaks access to the `xhr` property Note: This commit should not make it upstream in the current state. The matter of fixing access to the `xhr` property must be addressed. Relates to #319
@sandstrom check out that commit when you get a chance ^^ The tests are going to fail, due to the const promise = service.request('/foo');
console.log(promise.xhr); the code that would normally attach the Aside from the |
Thinking about it more, I suppose it makes sense. An |
Unfortunately, this whole I think that the best option is honestly to just asynchronously create the headers and then synchronously pass them on a per-request basis. You could probably add a method to the service that does it for every request if that's what you need. If forking was the solution you were going to go for, how were you going to solve the problem of the value of |
Yes, it was something like that (your commit) that I had in mind. But we're just going to switch to ember-fetch instead, since we are moving away from jQuery. Since this addon is ment to keep using jQuery Ajax I don't think it makes sense to spend too much time on it. There are other solutions to async headers, that doesn't require any modifications to this addon (as you mentioned). So I think we should just close this issue. |
Alright, sounds good to me. It's a shame I couldn't get this working, I love the idea of having any property be settable in an |
Sometimes the headers need to be set after resolving some promise. For example this issue or use-cases where an authorization token is stored in async storage such as IndexedDB.
I'd suggest switching the method to
buildHeaders
(or something similarly named), which can return a hash or a promise that resolves with a hash.Thoughts?
The text was updated successfully, but these errors were encountered: