【问题标题】:How to properly return value in async function when there are lot of callbacks有很多回调时如何在异步函数中正确返回值
【发布时间】:2017-11-02 10:40:45
【问题描述】:

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

我不想使用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);
                }
            });
        });
    });
};

【问题讨论】:

  • 您检查过async 模块吗?它将为您节省很多头疼
  • @borislemke async.parallel 似乎不接受第一个参数的承诺,我不想做任何奇怪的黑客攻击并将承诺转换为回调,我试图让代码变得更好尽可能

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


【解决方案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);
};

【讨论】:

  • 实际上,它会将undefined 传递给结果集,不过没关系,只是在答案中注明会很好
  • 现在开始有点乱了哈哈,但是你可以返回 false 并且只返回 filter 那些。
【解决方案2】:

您可以使用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);
});

因此,在您的情况下,您需要将 someModuleFirst.search(query) 更改为类似 someModuleFirst.search(query).catch(e =&gt; e) 的东西

【讨论】:

  • 谢谢!这是个好主意,不过我还不会接受,也许有人有更好的方法
猜你喜欢
  • 1970-01-01
  • 2016-01-14
  • 1970-01-01
相关资源
最近更新 更多