1

我正在使用本机 Promise 将一堆 XmlHttpRequests 组合成一个结果,我认为我得到了它的工作,请参阅http://jsfiddle.net/pjs06hdo/ (对 flickr api 的随机调用,请参阅控制台以了解实际情况按什么顺序)

可能会有更短的实现,但是通过这段代码,我可以理解发生了什么。

但随后出现了愚蠢的 JSONP :-( 事实证明,实际的目标站点不允许跨站点请求,我必须使用提供的 jsonP 端点(再次用 flickr 模拟)我被困在这里:那个愚蠢的全球回调不符合我的基本理解Promise

我认为解决方案与如何将现有回调 API 转换为承诺?.

我试图实现这一点,但它只能部分工作:http: //jsfiddle.net/b33bj9k1/没有实际输出,只有控制台消息,抱歉。但是在那里你可以看到有 3 个调用来创建 Promise,但是resolve(),jsonFlickrApiAsync()只被调用一次。

使用 Promise 处理 jsonP 回调的正确方法是什么,这样我就可以Promise.all()像上面的 XmlHttpRequest 版本一样处理结果?

请不要使用 jQuery - 我想了解真正发生的事情

4

1 回答 1

3

这不是 promise 的问题,这是JSONP的问题。由于它使用全局回调,因此您需要为每个请求使用不同的回调 - 具有不同的名称。对于 Flickr,这意味着您必须使用他们的jsoncallbackurl 参数。参数名称可能因您的实际端点而异。


但是,您对承诺的使用确实很奇怪。通常,您会为每个请求使用一个 Promise 来表示该请求的结果。您故意只创建一个全局承诺,这是行不通的。

function loadJSONP(url, parameter="callback") {
    var prop = "loadJSONP.back" + loadJSONP.counter++;
    var script = document.createElement("script");
    function withCleanUp(r) {
        return (x) => {
            loadJSONP[prop] = null;
            document.head.removeChild(script);
            r(x);
        }
    }
    return new Promise((resolve, reject) => {
        loadJSONP[prop] = withCleanUp(resolve);
        script.onerror = withCleanUp(reject);
        // setTimeout(script.onerror, 5000); might be advisable

        script.src = url+"&"+parameter+"="+prop;
        document.head.appendChild(script);
    });
}
loadJSONP.counter = 0;
于 2015-03-12T23:40:31.820 回答