问题描述
限时送ChatGPT账号..现场演示>
给定以下函数:
function isGood(number) {var defer = $q.defer();$超时(功能(){如果(<数字上的某些条件>){defer.resolve();} 别的 {defer.reject();}}, 100);返回 defer.promise;}
和一组数字(例如 [3, 9, 17, 26, 89]
),我想找到 第一个好"数字.我希望能够做到这一点:
var arr = [3, 9, 17, 26, 89];findGoodNumber(arr).then(function(goodNumber) {console.log('找到好号码:' + goodNumber);}, 功能() {console.log('没有找到好的数字');});
这是一种可能的递归版本来实现这一点:DEMO
function findGoodNumber(numbers) {var defer = $q.defer();if (numbers.length === 0) {defer.reject();} 别的 {var num = numbers.shift();isGood(num).then(function() {defer.resolve(num);}, 功能() {findGoodNumber(numbers).then(defer.resolve, defer.reject)});}返回 defer.promise;}
我想知道是否有更好的(也许是非递归的)方法?
解决方案不知道有没有更好的方法?
是的.避免延迟反模式!
function isGood(number) {返回 $timeout(function() {如果(<数字上的某些条件>){退货号码;//用数字解析,简化下面的代码} 别的 {throw new Error("...");}}, 100);}函数 findGoodNumber(numbers) {if (numbers.length === 0) {返回 $q.reject();} 别的 {返回 isGood(numbers.shift()).catch(function() {返回 findGoodNumber(numbers);});}}
<块引用>
也许是非递归的?
您可以制定一个循环来链接许多 then
调用,但是在这里递归绝对没问题.如果你真的想要循环,它可能看起来像这样:
function findGoodNumber(numbers) {返回 numbers.reduce(function(previousFinds, num) {返回 previousFinds.catch(function() {返回 isGood(num);});}, $q.reject());}
然而,这效率较低,因为它总是查看所有数字
.递归"版本会懒惰地评估它,如果当前数字不好,只会再做一次迭代.
也许更快?
您可以并行触发所有 isGood
检查,并等待第一个满足的返回.根据 isGood
的实际作用以及可并行化的程度,这可能更好".不过,它可能会做很多不必要的工作;您可能想要使用支持取消的承诺库.
一个使用 Bluebird 库的例子,它有一个 any
辅助函数专用于此任务:
function findGoodNumber(numbers) {返回 Bluebird.any(numbers.map(isGood))}
LIVE DEMO
Given the following function:
function isGood(number) {
var defer = $q.defer();
$timeout(function() {
if (<some condition on number>) {
defer.resolve();
} else {
defer.reject();
}
}, 100);
return defer.promise;
}
and an array of numbers (e.g. [3, 9, 17, 26, 89]
), I would like to find the first "good" number. I would like to be able to do this:
var arr = [3, 9, 17, 26, 89];
findGoodNumber(arr).then(function(goodNumber) {
console.log('Good number found: ' + goodNumber);
}, function() {
console.log('No good numbers found');
});
Here is one possible recursive version to implement this: DEMO
function findGoodNumber(numbers) {
var defer = $q.defer();
if (numbers.length === 0) {
defer.reject();
} else {
var num = numbers.shift();
isGood(num).then(function() {
defer.resolve(num);
}, function() {
findGoodNumber(numbers).then(defer.resolve, defer.reject)
});
}
return defer.promise;
}
I wonder if there is a better (maybe non-recursive) way?
解决方案I wonder if there is a better way?
Yes. Avoid the deferred antipattern!
function isGood(number) {
return $timeout(function() {
if (<some condition on number>) {
return number; // Resolve with the number, simplifies code below
} else {
throw new Error("…");
}
}, 100);
}
function findGoodNumber(numbers) {
if (numbers.length === 0) {
return $q.reject();
} else {
return isGood(numbers.shift()).catch(function() {
return findGoodNumber(numbers);
});
}
}
maybe non-recursive?
You can formulate a loop that chains lots of then
calls, however recursion is absolutely fine here. If you really wanted the loop, it might look like this:
function findGoodNumber(numbers) {
return numbers.reduce(function(previousFinds, num) {
return previousFinds.catch(function() {
return isGood(num);
});
}, $q.reject());
}
This is however less efficient, as it always looks at all numbers
. The "recursive" version will evaluate it lazily, and only do another iteration if the current number was not good.
maybe faster?
You can fire all isGood
checks in parallel, and wait for the first fulfilled to return. Depending on what isGood
actually does and how well that is parallelizable, this might be "better". It potentially does a lot of unnecessary work, though; you may want to use a promise library that supports cancellation.
An example using the Bluebird library, which has a any
helper function dedicated to this task:
function findGoodNumber(numbers) {
return Bluebird.any(numbers.map(isGood))
}
这篇关于Javascript:如何使用承诺迭代数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
更多推荐
[db:关键词]
发布评论