简体   繁体   中英

How to get/demonstrate asynchronous behavior in JavaScript promises

I read that

Promises also ensure order-independence. Separating the producer and consumer, so that they can execute independently, is the crux of asynchronous programming. With a promise, you can give a promise to a consumer before giving a resolver to a producer. They can then produce or consume on their own schedule and the promise synchronizes.

Trying to understand the Order Independence described above, I am writing up some code to hopefully demonstrate this. Basically, I wanted to create two asynchronous promises (based on downloading two images at two different times in partA() and partB() ), and then resolve both using all .

var axios = require('axios');
function loadImage(imgsrc) {
    return axios.get(imgsrc);
}
function partA() {
    var promise1 = loadImage("http://cn.bing.com/s/a/hp_zh_cn.png");
    var promise2 = setTimeout(partB,20000);
    Promise.all([promise1, promise2]).then(function() {
    console.log("The images are loaded");
    });
};

function partB () {
    return loadImage("http://cn.bing.com/s/a/hpc20.png");
};

partA();

Here are my issues and questions are:

  1. When executing partA() in the last line, I expected that I had to wait 20 seconds to see the success message because of the var promise2 = setTimeout(partB,20000); line (I had hoped that the two downloads happens 20 seconds apart from each other, for illustration purposes). Maybe I didn't use setTimeout right. But in any case, I got the success message almost immediately after I call partA() in the babel-node REPL. How do I properly get the delay?

  2. In this example (if correct), how can I interpret the Order Independence in terms of produce or consume on their own schedule ? Where are the sites of production and consumption?

(This is with babel-node 6.24.1 with --presets es2015 under Ubuntu 16.04)

The problem is, that setTimeout does not return a Promise. You have to insert a promise which executes a timeout to Promise.all.

function partA() {
     var promise1 = loadImage("http://cn.bing.com/s/a/hp_zh_cn.png");
     var promise2 = new Promise((resolve, reject) => {
         setTimeout(() => {
             return resolve(partB);
         }, 20000);
     });
     Promise.all([promise1, promise2]).then(function() {
         console.log("The images are loaded");
     });
 };

 function partB() {
     return loadImage("http://cn.bing.com/s/a/hpc20.png");
 };

 partA();

In this case, promise2 is actually a promise, which resolves with partB result, after 20 seconds.

setTimeout does not return a promise.

To see order independence at work consider this example:

var promise1, promise2;
promise1 = loadImage("http://cn.bing.com/s/a/hp_zh_cn.png");
promise2 = loadImage("http://cn.bing.com/s/a/hpc20.png");
promise1.then(function () {
    console.log("promise1 finished");
});
promise2.then(function () {
    console.log("promise2 finished");
});
Promise.all([promise1, promise2]).then(function() {
    console.log("both finished");
});

The output of this script can be either:

promise1 finished
promise2 finished
both finished

or

promise2 finished
promise1 finished
both finished

It just depends on which request completes earlier. If you want a more controlled example consider this:

var promise1, promise2;
promise1 = create_timeout_promise(20);
promise2 = create_timeout_promise(10);

function create_timeout_promise(timeout) {
    var promise;
    promise = new Promise(function (resolve) {
        setTimeout(resolve, timeout);
    });
    return promise;
}

Now the exepcted output is:

promise2 finished
promise1 finished
both finished

Because promise 2 is going to resolve first.

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