2016-08-04 9 views
0

以下の関数は、各単語の情報のためにapiを呼び出し、definitionsオブジェクトにデータを保存します。私は、任意のデータを返す前に、サーバーの応答を待つことを約束してきました。javascriptでの解決関数promiseが一貫して動作しない

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:未定義のプロパティ '0'を読み取れません"という行が表示されますコードはobj[this.id][0].textです。

私はonreadystate無名関数にこの条件に追加してみました:

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

が、それは何も解決しません。

答えて

0

条件は正しいですが、実行されたコードは正しくありません。 はちょうどこのような何か:

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

このコード例に過ぎない、あなたはあなたのためにそれが適して作ることができます:あなたのコードに続いて

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

define(arr)への呼び出しは、このようなものが見えるように!

1

responseTextは文字列です。あなたはここにJSONとしてそれを解析している:

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

見つからない定義の問題は全くあなたの要求コードではありません。どこにあなたが約束の結果を使用しているのかは、定義配列が空であるかどうかを調べるべき場所です。エラーが発生した場所は、有望な音:

… 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をキーを数えて再実装しています。 1つの単語を定義するための別の関数を作成することをお勧めします。

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:未定義(...)のプロパティ 'word'を読み取ることができません" – Michael

関連する問題