当有很多回调时,如何在异步函数中正确返回值

时间:2017-06-01 10:19:40

标签: javascript node.js asynchronous ecmascript-6 async-await

我有一个异步函数,调用其他异步函数,当它们全部完成后,我将返回结果。

我不想使用Promise.all,因为如果这些功能失败,我就不会将它们添加到我的搜索结果中。

ATM我的代码看起来像这样。它有效,但我不喜欢new Promise,我想用ES6异步方式做,所以callAll函数应该看起来像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);
                }
            });
        });
    });
};

2 个答案:

答案 0 :(得分:1)

您可以使用Promise.all,您唯一需要做的就是缓存拒绝并将其转化为解决方案。



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);
});
&#13;
&#13;
&#13;

因此,在您的情况下,您需要将someModuleFirst.search(query)更改为此类内容someModuleFirst.search(query).catch(e => e)

答案 1 :(得分:1)

您可以将代码减少到以下内容。您可以从catch处理程序返回false,然后过滤掉不会传递到结果集中的数据。

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);
};