2016-08-04 55 views
0

下面的函數需要一個單詞數組,調用每個單詞的信息api並將數據保存在definitions對象中。我已經使用諾言在返回任何數據之前等待服務器響應。javascript中的解析函數承諾並不一致

function define(arr) { //pyramid of doom at the expense of adding abstraction 
     return new Promise(function(resolve, reject) { 
     var client = []; 
     var definitions = {}; 
     for (var i = 0, len = arr.length; i < len; i++) { 
      (function(i) { 
       client[i] = new XMLHttpRequest(); 
       client[i].onreadystatechange = function() { 
        if (client[i].readyState === 4 && client[i].status === 200) { 
        definitions[arr[i]] = JSON.parse(client[i].responseText); 
         if (Object.keys(definitions).length === arr.length) { 
         resolve(definitions); 
         } 
        } 
       }; 
       client[i].open('GET', 'http://api.wordnik.com:80/v4/word.json/' + arr[i] + 
       '/definitions?limit=1&includeRelated=false&sourceDictionaries=all&useCanonical=false&includeTags=false&api_key=737061636520696e74656e74696f6e616c6c7920626c616e6', 
       true); 
       client[i].send(); 
       })(i); 
      } 
     }); 
    } 

當與arr參數的每一個元素是在Wordnik API數據庫上面的程序工作正常的話。當一個非單詞被傳入時,程序崩潰。我想這樣做,所以任何非單詞都被省略或顯示「未找到定義」。

解析函數創建一個單擊事件處理程序,如果一個非字傳遞給define,那麼當通過單擊觸發事件處理程序時,出現錯誤「Uncaught TypeError:無法讀取undefined屬性'0'代碼爲obj[this.id][0].text

我嘗試添加在此條件的onreadystate匿名函數:

if (client[i].responseText[0] === undefined) { 
    client.responseText[0] = { 
     word: arr[i], 
     text: 'Definition not found' 
    }; 

,但它不能解決任何事情。

回答

0

您的條件正確,但執行的代碼不正確。 就做這樣的事情:

if (client[i].responseText[0] === undefined) { 
    reject('Word not found'); 
} 

然後在你的代碼進行調用define(arr)看起來是這樣的:

define(arr).catch(function(error) { 
    alert(error); 
}); 

此代碼只是一個例子,你可以把它適合你!

1

responseText是一個字符串。你在這裏解析它爲JSON:

definitions[arr[i]] = JSON.parse(client[i].responseText); 

定義沒有找到的問題根本不在你的請求代碼中。無論你在哪裏使用promise的結果都是你應該檢查定義數組是否爲空的地方。發生錯誤的地方聽起來前途:

… the error "Uncaught TypeError: Cannot read property '0' of undefined" appears for a line with the code obj[this.id][0].text .

之前閱讀obj[this.id][0].text,確保obj[this.id].length !== 0

var definitions = obj[this.id]; 
var something = 
    definitions.length === 0 ? 
     'Definition not found' : 
     definitions[0].text; 

此外,你通過計數鍵來重新實現Promise.all。我建議做一個單獨的函數來定義一個單詞。

var API_KEY = '737061636520696e74656e74696f6e616c6c7920626c616e6'; 

function queryString(map) { 
    return '?' + 
     Object.keys(map) 
      .map(function (key) { 
       return key + '=' + encodeURIComponent(map[key]); 
      }) 
      .join('&'); 
} 

function defineWord(word) { 
    return new Promise(function (resolve, reject) { 
     var request = new XMLHttpRequest(); 
     var uri = 
      'http://api.wordnik.com/v4/word.json/' + encodeURIComponent(word) + 
      '/definitions' + queryString({ 
       limit: 1, 
       includeRelated: false, 
       sourceDictionaries: 'all', 
       useCanonical: false, 
       includeTags: false, 
       api_key: API_KEY, 
      }); 

     request.addEventListener('error', reject); 
     request.addEventListener('load', function() { 
      resolve(this.response); 
     }); 

     request.responseType = 'json'; 
     request.open('GET', uri, true); 
     request.send(null); 
    }); 
} 

function define(words) { 
    return Promise.all(words.map(defineWord)) 
     .then(function (results) { 
      var definitions = {}; 

      results.forEach(function (result, i) { 
       definitions[words[i]] = result; 
      }); 

      return definitions; 
     }); 
} 
+0

謝謝你是正確的問題沒有在請求我認爲。出於某種原因,當我傳入一個非單詞時,它會以某種方式導致定義對象中斷。我想我必須用更好的信息提出一個新的問題。 – Michael

+0

@Michael:你使用調試器檢查了'this.id'和'obj'的值嗎? – Ryan

+0

是的this.id工作正常,顯示被點擊元素的ID。 Obj顯示「TypeError:無法讀取未定義(...)的屬性'字' – Michael