在javascript承诺中解析函数不会表现得一致

时间:2016-08-04 00:18:43

标签: javascript promise

下面的函数采用一个单词数组调用api来获取每个单词的信息,并将数据保存在definitions对象中。在返回任何数据之前,我已使用承诺等待服务器响应。

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数据库中的单词时,上述程序可以正常工作。当传入非单词时,程序会崩溃。我想这样做,所以任何非单词都被省略或显示&#34;定义未找到。&#34;

resolve函数创建一个click事件处理程序,如果一个非单词传递给define,那么当一个点击触发事件处理程序时,错误&#34; Uncaught TypeError:无法读取属性&#39; 0&#39;未定义&#34;显示代码为obj[this.id][0].text的行。

我尝试将此条件添加到onreadystate匿名函数:

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

但它并没有解决任何问题。

2 个答案:

答案 0 :(得分:1)

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script> <ul class="list"> <li><a href="sleeping.html">Sleeping</a> </li> <li>Running</li> <li>Playing with Pepper</li> <li>Swimming</li> <li>Lounging</li> </ul> <button>Show List</button>是一个字符串。你在这里解析为JSON:

responseText

找不到定义的问题根本不在您的请求代码中。无论您在何处使用promise的结果,都应该检查定义数组是否为空。发生错误的地方听起来很有希望:

  

...错误&#34;未捕获的TypeError:无法读取属性&#39; 0&#39;未定义&#34;显示代码为definitions[arr[i]] = JSON.parse(client[i].responseText); 的行。

在阅读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 :(得分:0)

您的情况是正确的,但执行的代码却没有。 做这样的事情:

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

然后在您的代码中,调用define(arr)看起来像这样:

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

这段代码只是一个例子,你可以让它适合你!