仿Redis用来作前端浏览器的数据存储结构
用js写了一个类似redis存储结构的类库,目前只有的存储类型只有hash、set两个,
还没测试过性能,欢迎各位猿友能够帮我指出程序代码的缺陷,
后期有时间会完善其他几个类型的存储结构。
1 /************************************************************************** 2 * 类名: CRedis 3 * 描述: Redis数据库的JS版本 4 * 版本: 2.0 5 6 * 作者: 老狼 7 * 创建日期: 2016-07-13 8 * 更新日期: 2016-07-13 9 **************************************************************************/ 10 var C_REDIS_TYPE_NONE = 0; 11 var C_REDIS_TYPE_STRING = 1; 12 var C_REDIS_TYPE_LIST = 2; 13 var C_REDIS_TYPE_SET = 3; 14 var C_REDIS_TYPE_SORTEDSET = 4; 15 var C_REDIS_TYPE_HASH = 5; 16 var C_REDIS_TYPE_UNKNOW = 6; 17 18 var C_RESULT_NOTEXISTS = 0; 19 var C_RESULT_EXISTS = 1; 20 21 function CRedis() { 22 this.redis = {}; 23 this.redis.count = 0; 24 this.redis.db = []; 25 }; 26 27 CRedis.prototype.HashDelete = function (key, hashFields) { 28 if (this._isNullByParams(key, hashFields) || this._isNonStringByParams(key)) 29 return -1; 30 31 if (C_RESULT_NOTEXISTS == this.KeyExists(key)) 32 return undefined; 33 34 if (C_REDIS_TYPE_HASH != this.KeyType(key)) 35 return null; 36 37 var n = this.redis.db[key].length; 38 if ('[object String]' === Object.prototype.toString.call(hashFields)) { 39 if (C_RESULT_NOTEXISTS == this.HashExists(key, hashFields)) 40 return 0; 41 42 delete this.redis.db[key].dt[hashFields]; 43 --this.redis.db[key].length; 44 } else if ('[object Array]' === Object.prototype.toString.call(hashFields)) { 45 for (var i = 0; i < hashFields.length; ++i) { 46 if (this._isNullByParams(hashFields[i]) || C_RESULT_NOTEXISTS == this.HashExists(key, hashFields[i])) 47 continue; 48 49 delete this.redis.db[key].dt[hashFields[i]]; 50 --this.redis.db[key].length; 51 } 52 } else { 53 return -1; 54 } 55 56 if (0 == this.redis.db[key].length) 57 --this.redis.count; 58 59 return n - this.redis.db[key].length; 60 }; 61 CRedis.prototype.HashExists = function (key, hashField) { 62 if (this._isNullByParams(key, hashField) || this._isNonStringByParams(key, hashField)) 63 return -1; 64 65 if (C_RESULT_NOTEXISTS == this.KeyExists(key)) 66 return undefined; 67 68 if (C_REDIS_TYPE_HASH != this.KeyType(key)) 69 return null; 70 71 return (undefined === this.redis.db[key].dt[hashField] || 0 == this.redis.db[key].length) ? C_RESULT_NOTEXISTS : C_RESULT_EXISTS; 72 }; 73 CRedis.prototype.HashGet = function (key, hashField) { 74 if (this._isNullByParams(key, hashField) || this._isNonStringByParams(key, hashField)) 75 return -1; 76 77 if (C_RESULT_NOTEXISTS == this.KeyExists(key)) 78 return undefined; 79 80 if (C_REDIS_TYPE_HASH != this.KeyType(key)) 81 return null; 82 83 return C_RESULT_EXISTS == this.HashExists(key, hashField) ? this.redis.db[key].dt[hashField] : undefined; 84 }; 85 CRedis.prototype.HashGetAll = function (key) { 86 if (this._isNullByParams(key) || this._isNonStringByParams(key)) 87 return -1; 88 89 if (C_RESULT_NOTEXISTS == this.KeyExists(key)) 90 return undefined; 91 92 if (C_REDIS_TYPE_HASH != this.KeyType(key)) 93 return null; 94 95 return this.redis.db[key].dt; 96 }; 97 CRedis.prototype.HashKeys = function (key) { 98 if (this._isNullByParams(key) || this._isNonStringByParams(key)) 99 return -1; 100 101 if (C_RESULT_NOTEXISTS == this.KeyExists(key)) 102 return undefined; 103 104 if (C_REDIS_TYPE_HASH != this.KeyType(key)) 105 return null; 106 107 var a = []; 108 for (var k in this.redis.db[key].dt) 109 a.push(k); 110 111 return a; 112 }; 113 CRedis.prototype.HashLength = function (key) { 114 if (this._isNullByParams(key) || this._isNonStringByParams(key)) 115 return -1; 116 117 if (C_RESULT_NOTEXISTS == this.KeyExists(key)) 118 return undefined; 119 120 if (C_REDIS_TYPE_HASH != this.KeyType(key)) 121 return null; 122 123 return this.redis.db[key].length; 124 }; 125 CRedis.prototype.HashSet = function (key, hashField, hashValue) { 126 if (this._isNullByParams(key, hashField, hashValue) || this._isNonStringByParams(key, hashField)) 127 return -1; 128 129 if (C_RESULT_EXISTS == this.KeyExists(key) && C_REDIS_TYPE_HASH != this.KeyType(key)) 130 return null; 131 132 var a = { 133 "type": C_REDIS_TYPE_HASH, 134 "length": 0, 135 "dt": [] 136 }; 137 138 if (C_RESULT_EXISTS == this.KeyExists(key)) 139 a = this.redis.db[key]; 140 else 141 ++this.redis.count; 142 143 if (C_RESULT_NOTEXISTS == this.KeyExists(key) || C_RESULT_NOTEXISTS == this.HashExists(key, hashField)) 144 ++a.length; 145 146 a.dt[hashField] = hashValue; 147 148 this.redis.db[key] = a; 149 return 200; 150 }; 151 CRedis.prototype.HashValues = function (key) { 152 if (this._isNullByParams(key) || this._isNonStringByParams(key)) 153 return -1; 154 155 if (C_RESULT_NOTEXISTS == this.KeyExists(key)) 156 return undefined; 157 158 if (C_REDIS_TYPE_HASH != this.KeyType(key)) 159 return null; 160 161 var a = []; 162 for (var k in this.redis.db[key].dt) 163 a.push(this.redis.db[key].dt[k]); 164 165 return a; 166 }; 167 CRedis.prototype.KeyDelete = function (keys) { 168 if (this._isNullByParams(keys)) 169 return -1; 170 171 var n = this.redis.count; 172 if ('[object String]' === Object.prototype.toString.call(keys)) { 173 if (C_RESULT_NOTEXISTS == this.KeyExists(keys)) 174 return 0; 175 176 delete this.redis.db[keys]; 177 --this.redis.count; 178 } else if ('[object Array]' === Object.prototype.toString.call(keys)) { 179 for (var i = 0; i < keys.length; ++i) { 180 if (this._isNullByParams(keys[i]) || C_RESULT_NOTEXISTS == this.KeyExists(keys[i])) 181 continue; 182 183 delete this.redis.db[keys[i]]; 184 --this.redis.count; 185 } 186 } else { 187 return -1; 188 } 189 190 return n - this.redis.count; 191 }; 192 CRedis.prototype.KeyExists = function (key) { 193 if (this._isNullByParams(key) || this._isNonStringByParams(key)) 194 return -1; 195 196 return (0 == this.redis.count || undefined === this.redis.db[key] || 0 == this.redis.db[key].length) ? C_RESULT_NOTEXISTS : C_RESULT_EXISTS; 197 }; 198 CRedis.prototype.KeyType = function (key) { 199 if (this._isNullByParams(key) || this._isNonStringByParams(key)) 200 return -1; 201 202 return (C_RESULT_NOTEXISTS == this.KeyExists(key) || null == this.redis.db[key].type || 203 undefined == this.redis.db[key].type) ? C_REDIS_TYPE_NONE : this.redis.db[key].type; 204 }; 205 CRedis.prototype.SetAdd = function (key, value) { 206 if (this._isNullByParams(key, value) || this._isNonStringByParams(key)) 207 return -1; 208 209 if (C_RESULT_EXISTS == this.KeyExists(key) && C_REDIS_TYPE_SET != this.KeyType(key)) 210 return null; 211 212 if (C_RESULT_EXISTS == this.SetContains(key, value)) 213 return C_RESULT_EXISTS; 214 215 var a = { 216 "type": C_REDIS_TYPE_SET, 217 "length": 0, 218 "key": [], 219 "dt": [] 220 }; 221 222 if (C_RESULT_EXISTS == this.KeyExists(key)) 223 a = this.redis.db[key]; 224 else 225 ++this.redis.count; 226 227 a.key[JSON.stringify(value)] = null; 228 a.dt.push(value); 229 ++a.length; 230 231 this.redis.db[key] = a; 232 return 200; 233 }; 234 CRedis.prototype.SetContains = function (key, value) { 235 if (this._isNullByParams(key, value) || this._isNonStringByParams(key)) 236 return -1; 237 238 if (C_RESULT_NOTEXISTS == this.KeyExists(key)) 239 return undefined; 240 241 if (C_REDIS_TYPE_SET != this.KeyType(key)) 242 return null; 243 244 return undefined === this.redis.db[key].key[JSON.stringify(value)] ? C_RESULT_NOTEXISTS : C_RESULT_EXISTS; 245 }; 246 CRedis.prototype.SetLength = function (key) { 247 if (this._isNullByParams(key) || this._isNonStringByParams(key)) 248 return -1; 249 250 if (C_RESULT_NOTEXISTS == this.KeyExists(key)) 251 return undefined; 252 253 if (C_REDIS_TYPE_SET != this.KeyType(key)) 254 return null; 255 256 return this.redis.db[key].length; 257 }; 258 CRedis.prototype.SetPop = function (key) { 259 if (this._isNullByParams(key) || this._isNonStringByParams(key)) 260 return -1; 261 262 if (C_RESULT_NOTEXISTS == this.KeyExists(key)) 263 return undefined; 264 265 if (C_REDIS_TYPE_SET != this.KeyType(key)) 266 return null; 267 268 var r = this.redis.db[key].dt[this.redis.db[key].length - 1]; 269 270 delete this.redis.db[key].key[r]; 271 this.redis.db[key].dt = this.redis.db[key].dt.filter(function (item, i) { 272 return i !== this.redis.db[key].length - 1; 273 }, this); 274 --this.redis.db[key].length; 275 276 if (0 == this.redis.db[key].length) 277 --this.redis.count; 278 279 return r; 280 }; 281 CRedis.prototype.SetRemove = function (key, values) { 282 if (this._isNullByParams(key, values) || this._isNonStringByParams(key)) 283 return -1; 284 285 if (C_RESULT_NOTEXISTS == this.KeyExists(key)) 286 return undefined; 287 288 if (C_REDIS_TYPE_SET != this.KeyType(key)) 289 return null; 290 291 var n = this.redis.db[key].length; 292 if ('[object String]' === Object.prototype.toString.call(values) || '[object Object]' === Object.prototype.toString.call(values)) { 293 if (C_RESULT_NOTEXISTS == this.SetContains(key, values)) 294 return 0; 295 296 var jsonValue = JSON.stringify(values); 297 298 this.redis.db[key].dt = this.redis.db[key].dt.filter(function (item) { 299 return JSON.stringify(item) !== jsonValue; 300 }); 301 delete this.redis.db[key].key[jsonValue]; 302 --this.redis.db[key].length; 303 } else if ('[object Array]' === Object.prototype.toString.call(values)) { 304 for (var i = 0; i < values.length; ++i) { 305 if (this._isNullByParams(values[i]) || C_RESULT_NOTEXISTS == this.SetContains(key, values[i])) 306 continue; 307 308 var jsonValue = JSON.stringify(values[i]); 309 310 this.redis.db[key].dt = this.redis.db[key].dt.filter(function (item) { 311 return JSON.stringify(item) !== jsonValue; 312 }); 313 delete this.redis.db[key].key[jsonValue]; 314 --this.redis.db[key].length; 315 } 316 } else { 317 return -1; 318 } 319 320 if (0 == this.redis.db[key].length) 321 --this.redis.count; 322 323 return n - this.redis.db[key].length; 324 }; 325 CRedis.prototype.SetScan = function (key) { 326 if (this._isNullByParams(key) || this._isNonStringByParams(key)) 327 return -1; 328 329 if (C_RESULT_NOTEXISTS == this.KeyExists(key)) 330 return undefined; 331 332 if (C_REDIS_TYPE_SET != this.KeyType(key)) 333 return null; 334 335 return this.redis.db[key].dt; 336 }; 337 CRedis.prototype.SetGetRange = function (key, beg, end) { 338 if (this._isNullByParams(key, beg, end) || this._isNonStringByParams(key) || this._isNonNumberByParams(beg, end)) 339 return -1; 340 341 if (C_RESULT_NOTEXISTS == this.KeyExists(key)) 342 return undefined; 343 344 if (C_REDIS_TYPE_SET != this.KeyType(key)) 345 return null; 346 347 if (0 > beg || end < beg || end >= this.redis.db[key].length) 348 return undefined; 349 350 var a = []; 351 for (var i = beg; i <= end; ++i) { 352 if (this.redis.db[key].length <= i) 353 break; 354 355 a.push(this.redis.db[key].dt[i]); 356 } 357 358 return a; 359 }; 360 CRedis.prototype.SetGetValue = function (key, index) { 361 if (this._isNullByParams(key, index) || this._isNonStringByParams(key) || this._isNonNumberByParams(index)) 362 return -1; 363 364 if (C_RESULT_NOTEXISTS == this.KeyExists(key)) 365 return undefined; 366 367 if (C_REDIS_TYPE_SET != this.KeyType(key)) 368 return null; 369 370 if (0 > index || index >= this.redis.db[key].length) 371 return undefined; 372 373 return this.redis.db[key].dt[index]; 374 }; 375 CRedis.prototype._isNullByParams = function () { 376 return Array.prototype.slice.call(arguments).some(function (item) { 377 return undefined === item || null === item; 378 }); 379 }; 380 CRedis.prototype._isNonStringByParams = function () { 381 return Array.prototype.slice.call(arguments).some(function (item) { 382 return '[object String]' !== Object.prototype.toString.call(item); 383 }); 384 }; 385 CRedis.prototype._isNonNumberByParams = function () { 386 return Array.prototype.slice.call(arguments).some(function (item) { 387 return '[object Number]' !== Object.prototype.toString.call(item); 388 }); 389 };