Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
138 views
in Technique[技术] by (71.8m points)

javascript - Can Promise load multi urls in order?

promise then return a specified promise gives the following code snippet:

function get(url) {
  return new Promise(function(resolve, reject) {
    var req = new XMLHttpRequest();
    req.open('GET', url);

    req.onload = function() {
      if (req.status == 200) {
        resolve(req.response);
      }
      else {
        reject(Error(req.statusText));
      }
    };
    req.onerror = function() {
      reject(Error("Network Error"));
    };
    req.send();
  });
}

This function can be used as following:

get('story.json').then(function(response) {
  console.log("Success!", response);
}, function(error) {
  console.error("Failed!", error);
});

I want to use promise to load multi urls, such as

get('a.json').get('b.json')
// or get('a.json').then().get('b.json')

I have implemented it in other ways. But as I understand it, Promise can not do this work. Really ?

Add

In fact, I implemented a similar lib that help execute dynamic scripts in browsers:

Loader = (function() {

  var load_cursor = 0;
  var load_queue;

  var loadFinished = function() {
    load_cursor ++;
    if (load_cursor < load_queue.length) {
      loadScript();
    }
  }

  function loadError (oError) {
    console.error("The script " + oError.target.src + " is not accessible.");
  }


  var loadScript = function() {
    var url = load_queue[load_cursor];
    var script = document.createElement('script');
    script.type = "text/javascript";

    if (script.readyState){  //IE
        script.onreadystatechange = function(){
            if (script.readyState == "loaded" ||
                    script.readyState == "complete"){
                script.onreadystatechange = null;
                loadFinished();
            }
        };
    } else {  //Others
        script.onload = function(){
            loadFinished();
        };
    }

    script.onerror = loadError;

    script.src = url+'?'+'time='+Date.parse(new Date());
    document.body.appendChild(script);
  };

  var loadMultiScript = function(url_array) {
    load_cursor = 0;
    load_queue = url_array;
    loadScript();
  }

  return {
    load: loadMultiScript,
  };

})();  // end Loader


// load...

Loader.load(['http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js', './my.js']);
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Using Normal Promise Syntax

Chain Promises

You can chain your promises if you want them sequential:

get('a.json').then(function(a) {
    return get('b.json');
}).then(function(b){
    return get('c.json');
}).then(function(c) {
    // all done here
}), function(err) {
    // error here
});

Or in ES7, you can use async/await like this:

async function someFunction() {
    let a = await get('a.json');
    let b = await get('b.json');
    // do something with a and b here
    return something;
}

someFunction().then(result => {
    // all done here
}).catch(err => {
    // error here
});

Run Promises in Parallel

If you want them loaded in parallel, you can use Promise.all():

Promise.all([get('a.json'), get('b.json'), get('c.json')]).then(function(results) {
    // all done with results here
}, function(err) {
    // error here
});

Sequence Using .reduce()

Or, if you use the same code to process each result, you can load them sequentially using the reduce() design pattern:

['a.json', 'b.json', 'c.json'].reduce(function(p, item) {
    return p.then(function(){
        // process item here
    });
}, Promise.resolve()).then(function(result) {
    // all done here
}, function(err) {
    // error here
});

Sequence Using Bluebird's .map()

Or, if using the Bluebird promise library, it has Promise.map() which is very useful for parallel operations on an array

Promise.map(['a.json', 'b.json', 'c.json'], function(item) {
    // do some operation on item and return data or a promise
    return something;
}).then(function(results) {
    // all done
}, function(err) {
    // error here
});

Making get(x).get(y).get(z) Work

Extending the Promise

I was intrigued by the get(x).get(y).get(z) question using promises. I conjured up a way to do that in this working snippet:

function get(url) {
    function pget(u) {
        var p = this.then(function (result) {
            log(result);
            return get(u);
        });
        p.get = pget;
        return p;
    }
    var p = new Promise(function (resolve, reject) {
        setTimeout(function() {
            resolve(url);
        }, 500);
    });
    p.get = pget;
    return p;
}

get('a.json').get('b.json').get('c.json').then(function(result) {
    log(result);
    log("done");
}, function(err) {
    log("err");
});

function log(x) {
    var div = document.createElement("div");
    div.innerHTML = x;
    document.body.appendChild(div);
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...