简体   繁体   中英

How to properly return value in async function when there are lot of callbacks

I have an async function, that calls other async functions, and when they are all done, I'm returning the results.

I don't wanna use Promise.all , because in case any of these functions fail, I just don't add them to my results.

ATM my code looks like this. It works, but I don't like the new Promise , I wanna do it in ES6 async way, so the callAll function should look like const callAll = async (query) => {

const callAll = (query) => {
    return new Promise((resolve, reject) => {
        const results = [];

        const jobs = [
            {
                promise: someModuleFirst.search(query), 
                done: false
            },
            {
                promise: someModuleSecond.search(query),
                done: false
            },
            {
                promise: someModuleThird.search(query),
                done: false    
            }
        ];

        const areAllDone = () => {
            if(!jobs.filter((job) => !job.done).length) {
                return true;
            }
        };

        jobs.forEach((job) => {
            job.promise.then((result) => {
                job.done = true;

                results.push(result);

                if(areAllDone()) {
                    resolve(results);
                }
            }).catch((error) => {
                job.done = true; 

                if(areAllDone()) {
                    resolve(results);
                }
            });
        });
    });
};

You can use Promise.all the only thing you need to do is to cache rejection and turn it into resolve.

 function someAsyncFunction() { return new Promise((resolve, reject) => { setTimeout(function () { if (Math.round(Math.random() * 100) % 2) { return resolve('some result'); } reject('some rejection'); }) }, 1); } var promises = []; for (var i = 0; i < 10; i++) { // this is important part // catch block returns a promise with is resolved // so all promises now will resolve promises.push(someAsyncFunction().catch(function (reason) { return reason; })); } Promise.all(promises).then(function (results) { console.log('All resolved'); console.log(results); }).catch(function (reason) { console.error('Rejected'); console.log(reason); }); 

So in your case you need to change someModuleFirst.search(query) into some thing like this someModuleFirst.search(query).catch(e => e)

You could probably reduce your code to the following. You can return false from the catch handler, then filter out the data, which won't get passed into the result set.

const callAll = async (query) => {
    const modules = [someModuleFirst, someModuleSecond, someModuleThird];
    const jobs = modules.map((module) => module.search(query).catch(() => false);
    const results = await Promise.all(jobs);
    return results.filter(Boolean);
};

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