简体   繁体   中英

Wait for nested JS promise to finish before resolving original promise

I am new to Promises and I'm having a little trouble with the concept of waiting for a nested promise to finish all executions before resolving the original promise.

Original Code

function getSomething(text) {
    return new Promise(function (resolve, reject) {
        getElse(text).then(function (items) {
            if (items.length !== 0) {

                /* Stuff here */

                getElseElse(box).then(function (moreItems) {

                    /* Stuff here */

                    return array;
                }.then(function (array) {
                    var promise = new Promise(function (resolve, reject) {
                        /* anotherFunction() is asynchronous */
                        result = anotherFunction(array); <-- Spot 1
                    });
                    promise.then(function () { });
                });

                return resolve(result); <--- Spot 2

            }
            else {
                return resolve(null);
            }
        });
    });
};

Updated Code - better but still not fully working like I want.

function getSomething(text) {
    return getElse(text).then(function (items) {
        if (items.length !== 0) {

            /* Stuff here */

            return getElseElse(box).then(function (moreItems) {

                /* Stuff here */

                return array;
            }).then(anotherFunction);

        } else {
            return null;
        }
    });
}

Then, inside of the individual View page, I have this:

getSomething(text).then(function (result) {
    /* Do something here using result */
    /* But result is undefined and I think still pending */
});

I have optimized the original function using Thomas's help but the original call inside the view still seems to be continuing before result is formulated.

I want getSomething() to full complete and return result before I execute the code inside of the .then that is inside the view. So far, that is not being accomplished.

I have found a couple posts that have pointed me in what I think is the correct direction of Promise.all but I can't really seem to get anywhere with that information so I was hoping someone could help explain it for my specific situation.

The posts that have helped are:

  1. Promise Chain not waiting for promises to resolve before ending
  2. Wait until nested promises resolve
  3. Wait for promises inside Promise.all to finish before resolving it

Solution

The original issue was solved by Thomas in the marked answer. The final problem was solved inside of anotherFunction() upon further inspection.

Originally:

function anotherFunction(array) {
    return new Promise(function (resolve, reject) {
        return anotherGet(parcels).then(function (list) {
            /* Do stuff here without a return */
        });
    });
}

Fixed Version:

function anotherFunction(array) {
    return anotherGet(parcels).then(function (list) {
        /* Do stuff here */
        return list;
    });
}

First, avoid the Promise/Deferred antipattern. Rarely you need to create your own promises, usually you have some function that returns a Promise; use that.

Second, for the outer Promise to wait for a nesed PRomise, you need to return that nested Promise to the outer Promise.
Returning a Promise inside of then() will make the resulting Promise to resolve to the value of the Promise you retuned inside.

And last, something like .then(value => value) or .then(value => Promise.resolve(someFunction(value))) is pointless. Your wrapper around anotherFunction basically just passed through the argument and returned the result.

So, your Pseudocode should look something like this:

function getSomething(text) {
  return getElse(text).then(function (items) {
    if (items.length !== 0) {
      /* Stuff here */
      return getElseElse(box).then(function (moreItems) {
        /* Stuff here */
        return array;
      }).then(anotherFunction);
    } else {
      return null;
    }
  });
}

The basic trick is to make sure all of your resolve() calls are inside of the nested promises' then() methods.

Something along the lines of:

function getSomething(text) {
    return new Promise(function (resolve, reject) {
        getElse(text).then(function (items) {
            if (items.length !== 0) {

                /* Stuff here */

                getElseElse(box).then(function (moreItems) {

                    /* Stuff here */

                    return array;
                }.then(function (array) {
                    var promise = new Promise(function (resolve, reject) {
                        result = anotherFunction(array); <-- Spot 1
                    });
                    promise.then(function () { });

                    resolve(result); <--- Spot 2
                });    
            }
            else {
                resolve(null);
            }
        });
    });
};

If it needs to be nested in the promise.then() above, just stick it in there instead.

Also note that you don't need to return your resolves. Just call them.

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