在RSVP.Promise中包装jquery $ .ajax会炸毁整个应用程序

时间:2014-08-06 13:19:57

标签: jquery ajax ember.js ember-app-kit

更新1: 添加了另一个令人惊讶的非工作代码示例

更新2: 我回去开始重写我新实现的逻辑 - 现在可以正常工作


我正在使用Ember.js以及(现已弃用的)ember-app-kit布局和约定。主库版本是:

DEBUG: -------------------------------
DEBUG: Ember      : 1.4.0
DEBUG: Handlebars : 1.3.0
DEBUG: jQuery     : 2.1.0
DEBUG: -------------------------------

由于我打算将所有Ajax个请求放在一个地方,我想出了一个AjaxManager课程,该课程通过以下代码解决了我的所有要求:

function async (requestObj, successCallback, errorCallback) {

  requestObj.async = true; // just to be sure it's really asynchronous

  return $.when($.ajax(requestObj)).then(successCallback, errorCallback);
}

现在,随着我的进一步发展和我的代码的发展,我想将它包装在一个Ember.RSVP.Promise对象中,只是为了从我的model钩子等中调用它时有一些方便。所以我做了以下事情:

function promisedAsync (requestObj) {

  requestObj.async = true; // just to be sure it's really asynchronous

  return new Ember.RSVP.Promise(function (resolve, reject) {
    requestObj.success = function (data) {
       resolve(data);
    };

    requestObj.error = function () {
      reject(arguments)
    };

    $.ajax(requestObj);
  });
}

但是,现在发生的事情是我的第一个Ember.RSVP.Promise按预期得到解决,但所有进一步的Promise仍未解决/未被注意,这意味着它会挂起整个应用程序并驱动Chrome炸毁页面线程并收集更多内容更多的RAM(经常总结并且只能通过终止进程来停止)。

所以,基本上Ember.RSVP.Promise会爆炸$.ajax!我也尝试使用Ember.RSVP.defer(),或者使用jqXHR.beforeSend方法获取承诺/延期解决/拒绝,但它始终相同:第一个承诺得到解决/拒绝,其他所有承诺都挂起< / strong>并且永远不会再出现......


更新1:

我尝试使用普通XMLHttpRequest,留下jQuery.ajaxRSVP.defer()延迟对象,但是它给了我相同的结果

var set = Ember.set,
    get = Ember.get,
    RSVP = Ember.RSVP;
//....
// some application code
//...

promisedAsync: function (ajaxData) {
    var url = get(ajaxData, 'url'),
        method = get(ajaxData, 'type').toUpperCase(),
        xhr = new XMLHttpRequest(), // developing on Chrome, no IE needed (until now) :)
        data = get(ajaxData, 'data'),
        deferred = RSVP.defer();

    if (method === 'GET') {
      url = this._prepareUrl(url, data); // takes the data and concatenates it so that the params are in the URL
    }

    xhr.open(method, url);

    xhr.setRequestHeader('Content-Type', 'application/json');

    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4) {
        var response;

        try {
          response = JSON.parse(xhr.responseText);

          if (xhr.status === 200) {
            deferred.resolve(response);
          } else {
            deferred.reject(response);
          }

        } catch (e) {
          deferred.reject(e);
        }
      }
    };

    xhr.onabort = function () {
      deferred.reject('aborted');
    };

    if (method === 'GET') {
      xhr.send(null);
    } else {
      xhr.send(data);
    }

    return deferred.promise;
  }

更新2:

由于我没有想法而且没有一个错误代码或其他东西来自开发工具控制台,我终于还原了我的大量代码并进行了重置。我用较小的步骤/提交/块实现了代码,现在它可以工作了!我完全不知道是什么导致了这个问题,因为代码几乎相同......


有没有人遇到类似的问题,或者可以给我一些建议或暗示正确的方向?

2 个答案:

答案 0 :(得分:1)

我也没有看到任何问题,为了测试起见,将它包装在Ember.run语句中是好的,这里是Ember Data如何做到的副本(与你的几乎完全相同)。

 ajax: function(url, type, hash) {
    var adapter = this;

    return new Ember.RSVP.Promise(function(resolve, reject) {
      hash = adapter.ajaxOptions(url, type, hash);  // this is your requestObj

      hash.success = function(json) {
        Ember.run(null, resolve, json);
      };

      hash.error = function(jqXHR, textStatus, errorThrown) {
        Ember.run(null, reject, adapter.ajaxError(jqXHR));
      };

      Ember.$.ajax(hash); // this is the same thing as $.ajax
    }, "DS: RestAdapter#ajax " + type + " to " + url); // they name their promise
  }

答案 1 :(得分:0)

最后,只有一个还原&amp;重写做了伎俩 - 对于所有你未来的开发者来说都很难相似,但除了再做一次之外,我的问题没有真正的解决方案。这让我疯了!

我会接受这个答案作为我的问题的解决方案,以便可以关闭它。