简体   繁体   中英

How to wrap jsonP callback in native javascript Promise?

I'm playin with native Promise to combine a bunch of XmlHttpRequests into one result and I think I got it working, see http://jsfiddle.net/pjs06hdo/ (random calls to flickr api, see the console for what's actually going on in which order)

There might be shorter implementations but with this code I can understand what's going on.

But then there comes the stupid JSONP :-( as it turns out the actual target site does not allow Cross-site requests and I have to use a provided jsonP endpoint (again simulated with flickr) And here I'm stuck: that stupid global callback does not fit into my basic understanding of Promise

I think the solution has to do with explanations in How do I convert an existing callback API to promises? .

I tried to implement this but it works only partially: http://jsfiddle.net/b33bj9k1/ There is no actual output, only console messages, sorry. But there you can see that there are three calls to create the promises but the resolve() , the jsonFlickrApiAsync() gets called only once.

What would be the right way to handle jsonP callbacks with Promise so I can have an Promise.all() to deal with the results as in the XmlHttpRequest version above?

No jQuery please - I want to understand whats really going

This is not a problem with promises, this is a problem with 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 . The parameter name may vary for your actual endpoint.


However, your use of promises is indeed weird. Typically you'd use one promise per request, to represent that request's result. You are intentionally creating only one global promise, which cannot work.

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM