0

I am working on an open source EmberJS project that is making an Ajax request for information and then needs to resolve based on a dynamic subpart of the response.

  return new Promise((resolve, reject) => {
    const { resourceName, identificationAttributeName } = this.getProperties('resourceName', 'identificationAttributeName');
    const data         = {};
    data[resourceName] = { password };
    data[resourceName][identificationAttributeName] = identification;

    return this.makeRequest(data).then(
      (response) => run(null, resolve, response),
      (xhr) => run(null, reject, xhr.responseJSON || xhr.responseText)
    );
  });

....

makeRequest(data, options) {
  const serverTokenEndpoint = this.get('serverTokenEndpoint');
  const requestOptions = $.extend({}, {
    url:      serverTokenEndpoint,
    type:     'POST',
    dataType: 'json',
    data,
    beforeSend(xhr, settings) {
      xhr.setRequestHeader('Accept', settings.accepts.json);
    }
  }, options || {});

  return $.ajax(requestOptions);
}

In the end, I need the success response to run something like

(response) => run(null, resolve, response[resourceName])

but inside the response function, I have no access to the resourceName. How would I send this in?

here is the transpiled code:

  var _this = this;

  return new Promise(function (resolve, reject) {
    var _getProperties2 = _this.getProperties('resourceName', 'identificationAttributeName');

    var resourceName = _getProperties2.resourceName;
    var identificationAttributeName = _getProperties2.identificationAttributeName;

    var data = {};
    data[resourceName] = { password: password };
    data[resourceName][identificationAttributeName] = identification;

    return _this.makeRequest(data).then(function (response) {
      run(null, resolve, response);
    }, function (xhr) {
      return run(null, reject, xhr.responseJSON || xhr.responseText);
    });

1 Answers1

1

but inside the response function, I have no access to the resourceName.

Of course you do - just try it out! Arrow functions create closures as well.

Btw, you should avoid the Promise constructor antipattern (and rather make run return something), and you should dodge jQuery deferreds in favour of real promises.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • jQuery 3.0 is available http://blog.jquery.com/ . Have you tested that versions deferred , promise implementations to verify that _"jQuery.Deferred is now Promises/A+ compatible" is accurate ? – guest271314 Feb 29 '16 at 18:19
  • @guest271314: Still: 1) it's unlikely OP is already using it 2) the implementation is horrible and lacks many features 3) OP seems to want to use the native `Promise`s – Bergi Feb 29 '16 at 18:24
  • @guest271314: No, I have not tested it, but I believe them. Have you tested it? Should I need to? – Bergi Feb 29 '16 at 18:25
  • Would "Is "jQuery.Deferred is now Promises/A+ compatible" is accurate ?" be a good Question for SO ? – guest271314 Feb 29 '16 at 18:26
  • Yes, have tested it. Though probably not as thoroughly as you would; that is; what to test for ? – guest271314 Feb 29 '16 at 18:26
  • I'd love for your first statement to be true...but it simply isn't available inside my response function – Kyle Mellander Feb 29 '16 at 18:26
  • @guest271314 I don't think so. The answer is trivial and can easily be researched. The test suite is readily available to everyone (and probably part of jQuery as well) – Bergi Feb 29 '16 at 18:26
  • @KyleMellander: What exactly does "isn't available" mean? Are you getting an exception (which one)? What value do you get there when you attempt to log it (or what does your debugger say)? Are you transpiling the ES6 code (and what does the result look like)? – Bergi Feb 29 '16 at 18:28
  • @Bergi - it looks like it had something to do with Bable transpiling when looking at the transpiled code, I could access the data – Kyle Mellander Feb 29 '16 at 18:30
  • @KyleMellander: If the transpiled code works, then what does not work? – Bergi Feb 29 '16 at 18:32
  • @Bergi - _this is available, but if I try to define it before compiling, it is not available – Kyle Mellander Feb 29 '16 at 18:35
  • @KyleMellander: I thought the issue was with `resourceName`, not with `this` (or `_this`)? – Bergi Feb 29 '16 at 18:37
  • @Bergi - resourceName is also available by doing this.get('resourceName') so if I have access to this, then I can grab resourceName – Kyle Mellander Feb 29 '16 at 18:40
  • @KyleMellander: That should work as well, `this` will have the same value as in the excutor scope (where you use `getProperties`). But notice that calling `get('resourceName')` again is prone to race conditions, the value could have changed as the callback is asynchronous. Why not just use the `resourceName` variable, which already is in scope? – Bergi Feb 29 '16 at 18:45
  • I think that I found the solution. It looks like a closure issue with the Arrow function. When I switched to function(response) { run(null, resolve, response[resourceName]) } everything worked as intended. – Kyle Mellander Feb 29 '16 at 18:48
  • @KyleMellander: Isn't that exactly what you had in your question? – Bergi Feb 29 '16 at 18:57
  • @Bergi - To be honest, I have no clue what changed. Everything seems to be working as intended now and I don't really understand what changed – Kyle Mellander Feb 29 '16 at 19:00
  • @KyleMellander: Hm, that arrow function had a return value while the `function` yields `undefined`; but that's hardly the cause. – Bergi Feb 29 '16 at 19:01
  • @Bergi - with closure - are variables not scoped in unless they are used? – Kyle Mellander Feb 29 '16 at 19:03
  • @KyleMellander: In effect, yes, but actually the other way round: They're (in theory) always scoped in, but optimised out (by implementations) when not used. Given that you are using `resourceName` in both versions, it doesn't matter anyway. – Bergi Feb 29 '16 at 19:05
  • @Bergi - Well, I really appreciate you taking the time to help me out with this. I've learned a lot even if I still don't fully understand why I had the issue originally. – Kyle Mellander Feb 29 '16 at 19:07