为什么我的 JavaScript 使用 RSVP.js 库的 Promise 在我的所有 Promise 都成功后返回错误?

Why is my JavaScript Promises using the RSVP.js library returning an error after all my Promises succeeded?

下面的简单演示 JavaScript 代码使用 RSVP.js Promise 库 https://github.com/tildeio/rsvp.js/ 使用 AJAX 加载一些 JSON 数据,并在完成时触发一些加载所有 JSON 数据后的代码。

之后它在链式 then() 调用中运行非 ajax 函数

我所有的 Promise 都成功了,但是 returns 最后也是一个错误!

我不确定为什么错误是 运行?

JSFiddle 演示:http://jsfiddle.net/jasondavis/fttzoggj/3/

var jsonPromiseCache = {};



// AJAX function to load JSON data using Promise()
var getJsonDataPromise = function(url, key) {

  if (!jsonPromiseCache[key]) {
     jsonPromiseCache[key] = new RSVP.Promise(function(resolve, reject){
      // If jsonPromiseCached data is not set then make AJAX requiest to get it


        var client = new XMLHttpRequest();
        client.open("GET", url);
        client.onreadystatechange = handler;
        client.responseType = "json";
        client.setRequestHeader("Accept", "application/json");
        client.send();

        console.log('---- "client" XMLHttpRequest/AJAX  variable ======= ',client);


        function handler() {
          if (this.readyState === this.DONE) {
            // On AJAX success, resolve() our Promise() and set result to cached variable
            // to avoid duplicate AJAX requests for this jsonCache[key] Data where "key"
            // is used to assign to each AJAX endpoint URL/request of JSON data...
            // (milestones, tasks, users, etc...)
            if (this.status === 200) {
                jsonPromiseCache[key] = this.response;

                console.log('---- jsonPromiseCache['+key+'] ====== ',jsonPromiseCache[key]);

                // Resolve() the Promise() on AJAX success
                resolve(this.response);

            // On AJAX failure, reject() our Promise()
            }else{
                reject(this);
            }
          }
        };

      // If JSON data for this key is already jsonPromiseCached, then return the jsonPromiseCached version
      // instead of making a new AJAX request!
    });
  }
  return jsonPromiseCache[key];
};

新非ajax承诺

// testing a  non ajax Promise
function initDomEvents() {
    var eventsLoaded = true;

    //if (eventsLoaded) {
        jsonPromiseCache['domevents'] = eventsLoaded;

        console.log('---- initDomEvents() ran');

        // Resolve() the Promise() 
        //resolve(jsonPromiseCache['domevents']);
        resolve();

        // On false, reject() our Promise()
    //}else{
    //    reject();
    //}

};

示例使用演示

// usage loading JSON data with AJAX using Promises
var promises = {
    users: getJsonDataPromise('/echo/json/', 'users'),
    task: getJsonDataPromise('/echo/json/', 'task')
};


RSVP.hash(promises)
.then(function(results) {
  console.log('then() function ran on success of loading JSON data');
  console.log(results);
  console.log('results.users', results.users); // print the users JSON results
  console.log('results.task', results.task); // print the task JSON results
})
.then(initDomEvents)
.finally(function(){
  console.log('finally() function ran on success and failure.... It is always ran!');
})
.catch(function(reason){
  console.log('[ERROR] REASON:',reason.statusText); //if any of the promises fails.
});

更新

这个新演示 http://jsfiddle.net/jasondavis/fttzoggj/6/ 添加了第三个 Promise 而第三个没有得到 运行!第二个 Promise 函数 initDOmEvents() returns 现在这个错误...

ERROR] REASON: ReferenceError: resolve is not defined
    at initDomEvents (http://fiddle.jshell.net/_display/:91:9)
    at G (http://apollowebstudio.com/labs/js/sugarcrm-pm/js/rsvp.min.js:2:6009)
    at F (http://apollowebstudio.com/labs/js/sugarcrm-pm/js/rsvp.min.js:2:5928)
    at L (http://apollowebstudio.com/labs/js/sugarcrm-pm/js/rsvp.min.js:2:6661)
    at MutationObserver.h (http://apollowebstudio.com/labs/js/sugarcrm-pm/js/rsvp.min.js:2:1667)

添加了新代码...

// 测试非 ajax Promise

function initTaskModalLibraries() {
    var taskModalScriptsLoaded = true;

    if (taskModalScriptsLoaded) {
        jsonPromiseCache['inittaskmodallibraries'] = taskModalScriptsLoaded;

        console.log('---- initTaskModalLibraries() ran');

        // Resolve() the Promise() 
        //resolve(jsonPromiseCache['domevents']);
        resolve();

        // On false, reject() our Promise()
    }else{
        reject();
    }

};

RSVP.hash(promises)
.then(function(results) {
  console.log('then() function ran on success of loading JSON data');
  console.log(results);
  console.log('results.users', results.users); // print the users JSON results
  console.log('results.task', results.task); // print the task JSON results
})
.then(initDomEvents)
.then(initTaskModalLibraries)
.finally(function(){
  console.log('finally() function ran on success and failure.... It is always ran!');
})
.catch(function(reason){
  console.log('[ERROR] REASON:',reason); //if any of the promises fails.
});

更新 2

我现在在我的新的非ajax函数中看到我缺少new RSVP.Promise(function(resolve, reject){})

固定演示 http://jsfiddle.net/jasondavis/fttzoggj/8/

在您的 [ERROR] 日志行中,像这样删除 .statusText

.catch(function(reason){
  console.log('[ERROR] REASON:',reason); //if any of the promises fails.
});

您会看到这个可点击的错误:

[ERROR] REASON:
ReferenceError: resolve is not defined       initDomEvents()/_display/ (line 92)
G()                                          rsvp.min.js (line 2)
F()                                          rsvp.min.js (line 2)
L()                                          rsvp.min.js (line 2)
h()                                          rsvp.min.js (line 2)

这是一个 updated fiddle,我认为它符合您的预期。主要变化是:

return new RSVP.Promise(initDomEvents)  

在您的第一个 then 处理程序中,它将返回的结果传递给下一个 then(链接),

并更改 initDomEvents 的方法签名:

function initDomEvents(resolve, reject) {

这样就定义了resolve/reject。