我有一个奇怪的情况,我想在收到Rx Promise的结果并做一些检查后打破for循环。我所拥有的是以下内容:
<!-- assume the border-bottom is only applied to an active=clicked navigation tab -->
<h1 style="border-bottom: 3px solid green;">Tab1</h1>
<h1>Tab2</h1>
其中function getDrift(groups) {
var drift = {};
groups.forEach(function(group) {
if(group.type === 'something') {
for(var i = 0; i < group.entries.length; i++) {
fetchEntry(group.entries[i].id)
.then(function(entry) {
if(entry.type === 'someType'){
drift[entry._id] = getCoordinates(entry);
// break;
}
});
}
}
});
return drift;
}
基于id返回mongodb文档的Promise。如果满足fetchEntry
检查,我想打破当前if
的循环并继续下一组。
这可能吗?
由于
编辑:根据要求,群组对象如下所示:
group.entries
解决方案:我最终使用@MikeC的建议进行递归和回调以返回所需的值。谢谢大家!
答案 0 :(得分:6)
这是不可能的,因为Promises是异步的,这意味着then
won't execute until all other synchronous code completes.
如果您不想根据某些条件处理所有这些条件,我建议您创建一个函数,如果要继续,可以调用它。
(function process(index) {
if (index >= group.entries.length) {
return;
}
fetchEntry(group.entries[index])
.then(function(entry) {
if(entry.type === 'someType'){
drift[entry._id] = getCoordinates(entry);
// don't call the function again
} else {
process(index + 1);
}
});
})(0);
答案 1 :(得分:3)
传递给then()的函数不在for循环中调用。在for循环结束后调用(long)。这是异步编程模型的本质。
您需要重新组织代码,以便不使用for循环。相反,您需要在回调中启动下一次抓取,或者不要在适当时启动它。
PS。由于同样的原因,您无法返回由回调填充的对象:您的函数将返回空对象/调用回调之前
编辑:演示,但代码未经测试:
function getDrift(groups) {
var promise = ...;
var drift = {};
groups.forEach(function(group) {
if(group.type === 'something') {
var i = 0;
var processEntry = (function(entry) {
if(entry.type === 'someType'){
drift[entry._id] = getCoordinates(entry);
// We are finished, so complete our promise with
// the collected data
promise.success(drift);
return;
}
// increment our position in the array
i += 1;
// check to see if we are at the end of the array
if (i >= group.entries.length)
{ return; }
// now fetch the next entry from the array
fetchEntry(group.entries[i].id)
.then(processEntry);
});
// fetch the first entry
fetchEntry(group.entries[i].id)
.then(processEntry);
} // end if
}); // end forEach()
return promise;
}
答案 2 :(得分:0)
如果满足if检查,我想打破当前的循环 group.entries并继续下一组。
如果正确解释问题,请尝试使用Promise.all()
,Array.prototype.map()
function getDrift(groups) {
var drift = {};
var m = 0;
return Promise.all(groups.map(function(p) {
// if `p` contains `5` return `null`
// else multiply item within `p` by `10`
return p.indexOf(5) === -1 ? p.map(function(k) {
drift[m] = k * 10;
++m
}) : null
})).then(function(n) {
return drift
}, function(err) {
console.log(err)
})
}
// array containing `5` will not be processed
var res = getDrift([[1,2,3], [4,5,6], [7,8,9]])
.then(function(data) {
console.log(data)
})
&#13;
在问题
上将模式应用于js
function getDrift(groups) {
var drift = {};
return Promise.all(groups.map(function(group) {
return group.type === "something"
? Promise.all(group.entries.map(function(g, index) {
return fetchEntry(g.id).then(function(entry) {
if (entry.type === "someType") {
drift[entry._id] = getCoordinates(entry);
return Promise.reject(entry.type);
}
})
}))
: null
})).then(function() {
return drift
}, function(err) {
console.log(err)
})
}
// array containing `5` will not be processed
var res = getDrift(groups)
.then(function(data) {
console.log(data)
}, function(err) {
console.log(err)
})
答案 3 :(得分:0)
这可能是没有递归,但不是特别简单。
您可以使用以下组合:
forEach()
替换为Array#map()
以将groups
映射到承诺数组,for
循环替换为Array#reduce()
以构建.then()
链,这是&#34;易碎的&#34;通过发送它的错误路径。到目前为止最简单的事情是根据问题中的代码坚持使用drift
作为外部变量。通过承诺链交付数据也是可能的,但代码会更复杂。
function getDrift(groups) {
var drift = {};
// Map groups to an array of promises.
var promises = groups.map(function(group) {
if(group.type === 'something') {
// Here, replace the original `for` loop with `group.entries.reduce()` to build a .then() chain.
return group.entries.reduce(function(p, e) {
return p.then(function() {
return fetchEntry(e.id).then(function(entry) {
if(entry.type === 'someType') {
drift[entry._id] = getCoordinates(entry); // Yay!
throw false; // Throw almost anything here to skip the rest of the .then() chain.
} else {
return true; // Return almost anything here to carry on down the chain.
}
});
});
}, Promise.resolve()) // Resolved starter promise for the reduction.
.catch(function() { // If there was a match, we end up on the error path, and need to convert to success.
return true; // Return almost anything here.
});
} else {
return true; // Return almost anything here to make a positive entry on the `promises` array.
}
});
return Promise.all(promises) // Aggregate the promises.
.then(function() {
return drift; // and deliver the populated `drift` to the calling function
});
}
当getDrift()
返回一个承诺时,drift
仅在.then()回调中可供调用者使用:
getDrift(groups).then(function(drift) {
//do something with drift
});