Javascript/NodeJS:通过对象数组/集合中的id查找特定对象的最佳方法
Javascript/NodeJS: Best way to find an specific object by id inside an array/collection of objects
概述
所以我从数据库中提取了一个文档。里面是一个嵌套的对象集合。此嵌套集合中的每个对象都有一个"_id"属性。我想使用Javascript在这些对象上找到一个特定的"_id">
示例
http://jsfiddle.net/WilsonPage/tNngT/
替代示例
http://jsfiddle.net/WilsonPage/tNngT/3/
问题
- 我的例子是实现这一目标的最佳方式吗
- 这个会在Node.js中阻塞吗
是的,如果您只知道一个对象(保存在数组中(所包含的特定值,则需要在整个结构上循环并比较这些值。
正如您所做的一样,当您找到迭代(示例中的return
(时,中断迭代
因此,我对您的第一个问题的回答是是,就性能而言,这是正确和最好的方法。
我没有得到的是">Async"示例。您只是移动了代码并更改了结构。您的代码仍然处于"阻塞"状态,因为您正在使用普通的for-loop
进行搜索。如果该数组巨大,它将在循环完成所需的时间内阻止您的节点应用程序。
要真正实现异步,您需要去掉任何loop
。你需要用跑道计时器在结构上盘旋。
var findById = function(collection, _id, cb){
var coll = collection.slice( 0 ); // create a clone
(function _loop( data ) {
if( data._id === _id ) {
cb.apply( null, [ data ] );
}
else if( coll.length ) {
setTimeout( _loop.bind( null, coll.shift() ), 25 );
}
}( coll.shift() ));
};
然后像一样使用
findById( myCollection, 102, function( data ) {
console.log('MATCH -> ', data);
});
通过这种技术(这是一个简化的示例(,我们正在创建一个自调用匿名函数,并传入第一个数组项(使用.shift()
(。我们进行比较,如果找到了要查找的项,则执行调用方需要提供的回调函数。如果我们没有匹配,但数组仍然包含元素(检查.length
(,我们使用setTimeout
创建25ms的超时,并再次调用_loop
函数,这次是使用下一个数组项,因为.shift()
获取并删除第一个条目。我们重复这一步骤,直到没有留下任何项目或找到元素为止。由于setTimeout
为JS主线程(在浏览器上,UI线程(中的其他任务提供了做事的机会,因此我们不会阻止和破坏整个节目。
正如我所说,这可以得到优化。例如,我们可以在_loop()
方法中使用do-while
循环,也可以使用Date.now()
进行操作,直到我们超过50ms为止。如果我们需要更长的时间,以相同的方式创建timeout
,并再次重复上述操作(因此,在50ms内进行尽可能多的操作(。
如果速度真的是个问题,我会根据每个项目的_id对数组进行预排序,至少实现一个二进制搜索,如果不是更复杂的话。
您可以尝试使用二进制搜索,在大多数情况下它比线性搜索更快。正如jAndy所说,您仍然会使用标准的for循环进行阻塞,所以请查看一些节点异步库。首先想到的是async.js
为了解决我的问题,我乱用了async.js。我已经尝试使它尽可能地可重复使用,这样它就不会只是被锁定来搜索"_id"属性。
我的解决方案:
http://jsfiddle.net/WilsonPage/yJSjP/3/
假设您可以从_id生成唯一的字符串,则可以使用js的本地对象对其进行散列。
findById = (collection, _id, callback, timeout = 500, step = 10000)->
gen = ->
hash = {}
for value, i in collection
hash[value._id] = value
unless i % step then yield i
hash[_id]
it = gen()
do findIt = ->
{done, value} = it.next()
if done then callback value
else
console.log "hashed #{(value/collection.length*100).toFixed 0}%"
setTimeout findIt, timeout
- 为什么我的猫鼬对象 Id 请求返回一个空数组
- 基于变量创建json对象id
- Grails richui自动完成将对象传递给函数或更新对象ID
- 如何在jQuery中获取对象ID并将其与其他字符串组合
- 如何在 Javascript 中按 prev 对象 id 对对象数组进行排序
- 猫鼬对象 ID 不用作函数中的参数
- 如果对象 id 相同,如何合并对象
- 猫鼬对象 ID 不作为函数中的参数工作
- Parse.com / Javascript - 将用户对象ID字符串保存为用户指针
- 在 Javascript 中按对象 ID 分组
- JavaScript 通过 ID 获取元素与对象 ID
- 解析:保存后获取对象 ID
- 使用 jQuery 将点击的对象 ID 转换为变量以进行优化
- 返回匹配对象 id 的下一个和上一个对象
- 如何获取具有指针字段的对象 ID 的记录
- 使用javascript在parse.com中迭代对象id
- 如何在javascript中访问当前rails对象id
- 无法按对象id查询对象
- aspx客户端事件(javascript)中的发件人对象ID
- 通过对象id获取对象属性