如何在本机 javascript Promise 中包装 jsonP 回调?

How to wrap jsonP callback in native javascript Promise?

我正在使用本机 Promise 将一堆 XmlHttpRequest 组合成一个结果,我想我成功了,请参阅 http://jsfiddle.net/pjs06hdo/ (随机调用 flickr api,查看控制台以了解实际发生的情况)

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

但后来出现了愚蠢的 JSONP :-( 因为事实证明实际目标站点不允许跨站点请求,我必须使用提供的 jsonP 端点(再次用 flickr 模拟)我在这里卡住了:那个愚蠢的全局回调不符合我对 Promise

的基本理解

我认为解决方案与 How do I convert an existing callback API to promises? 中的解释有关。

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

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

不jQuery拜托-我想了解到底是怎么回事

这不是 promise 的问题,这是 JSONP. Since it uses global callbacks, you need to use different callbacks - with different names - for each request. For Flickr that means you have to use their jsoncallback url parameter 的问题。参数名称可能因您的实际端点而异。


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

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;