最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

ruby - Compacting arrays in JavaScript - Stack Overflow

programmeradmin0浏览0评论

What is JavaScript equivalent to Ruby's Array#pact?

Long version.... I followed the examples at blog.nemikor. His last example closes out old requests, but then pendings continues to be filled with obsolete requests. This looks like a memory leak to me.

My solution is to iterate over pendings with filter as below, but this seems like there may be a race condition between pendings.push and pendings = pendings.filter. Am I being paranoid? If a race condition exists, how should I fix it?

var pendings = [];

// there is a route
app.get('/some/path', function (request, response) {
  pendings.push({
    response: response,
    requestedAt: new Date().getTime()
  });
});

setInterval(function () {
  var expiration = new Date().getTime() - (1000 * 30);
  pendings = pendings.filter(function (pending, index) {
    if (pending.requestedAt > expiration) {
      return true;
    } else {
      pending.response.writeHead(408, { 'Content-Type': 'text/plain' });
      pending.response.end('');
    }
  });
}, 1000);

What is JavaScript equivalent to Ruby's Array#pact?

Long version.... I followed the examples at blog.nemikor.. His last example closes out old requests, but then pendings continues to be filled with obsolete requests. This looks like a memory leak to me.

My solution is to iterate over pendings with filter as below, but this seems like there may be a race condition between pendings.push and pendings = pendings.filter. Am I being paranoid? If a race condition exists, how should I fix it?

var pendings = [];

// there is a route
app.get('/some/path', function (request, response) {
  pendings.push({
    response: response,
    requestedAt: new Date().getTime()
  });
});

setInterval(function () {
  var expiration = new Date().getTime() - (1000 * 30);
  pendings = pendings.filter(function (pending, index) {
    if (pending.requestedAt > expiration) {
      return true;
    } else {
      pending.response.writeHead(408, { 'Content-Type': 'text/plain' });
      pending.response.end('');
    }
  });
}, 1000);
Share Improve this question asked May 30, 2011 at 23:20 ravinggeniusravinggenius 8681 gold badge6 silver badges15 bronze badges 3
  • 1 pact-like behavior – Zabba Commented May 30, 2011 at 23:24
  • MDC doco on filter if you need it. – RobG Commented May 31, 2011 at 0:36
  • Follow Zabba's link for an answer to the title question... – AShelly Commented Nov 19, 2012 at 16:16
Add a ment  | 

4 Answers 4

Reset to default 3

An old thread but it deserves an answer to the original question:

What is JavaScript equivalent to Ruby's Array#pact?

list1 = [null, 'no', 'nulls', null]

// With plain JS
jsFilter = list1.filter(function (obj) { return obj })

// With ES6
let filtered = list1.filter((obj) => obj)

//> (2) ["no", "nulls"]

console.log(es6Filter)

But there is a caveat, because:

filter() calls a provided callback function once for each element in an array and constructs a new array of all the values for which callback returns a value that coerces to true.

falsey = [false, 0, 0n, '', NaN, null, undefined]
truthy = [true, 1, ' ']

list2 = ['returns', 'only', 'truthy', 'values'].concat(truthy).concat(falsey)

let filtered = list2.filter((obj) => obj)

//> (7) ["returns", "only", "truthy", "values", true, 1, " "]

console.log(filtered)

In order to have it working like Ruby's pact, you can do:

falsey = [false, 0, 0n, '', NaN, null, undefined]
truthy = [true, 1, ' ']
list3 = ['works', 'like', "Ruby's", 'pact'].concat(truthy).concat(falsey)

let them_go = [null, undefined] // Just a fun with variable names
let filtered = list3.filter((obj) => { return !them_go.includes(obj) })

//> (12) ["works", "like", "Ruby's", "pact", true, 1, " ", false, 0, 0n, "", NaN]

console.log(filtered)

If you want to remove all the empty elements (empty Strings, Arrays, and Objects) from an array, you can check my answer here -> https://stackoverflow./a/59905255/3251051

References:

  • https://ruby-doc/core-2.6.5/Array.html#method-i-pact
  • https://developer.mozilla/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
  • https://developer.mozilla/en-US/docs/Glossary/Falsy
  • https://developer.mozilla/en-US/docs/Glossary/Truthy
  • http://kenglish.co/blog/2018/1/remove-null-elements-from-array-with-javascript

You have no threads in JavaScript, so there can be no race condition. All code is sequenced and will transfer control only after it's done running. So your interval function will run till pletion before any other function is going to touch pendings.

This holds for things like setTimeout and setInterval.

As an experiment: If you made a timeout using setTimeout to fire after 1 second. And after that you write a while-loop that blocks for 2 seconds, your timeout will fire after that, so much longer than 1 second.

Something crude:

var timer = setTimeout(function () {
    alert("hi!");
}, 1000);
var now = new Date();
var till = new Date(now + 2);
while(new Date() < till) {}   // block for 2 seconds

You may want to take a look at the Underscore.js library
http://documentcloud.github./underscore/

This provides many useful low-level functions to deal with collections, arrays and objects. It includes both a pact function (though I think it serves a different purpose to what you're looking for) and a filter function.

As long as you're not doing I/O, i.e., you are only doing in-memory operations, you are guaranteed to not be interrupted (due to the nature of the event loop).

Being so, be careful, if your collection is too long (like on the thousands or more), because you can block the event loop for some time, not letting the other requests be serviced.

发布评论

评论列表(0)

  1. 暂无评论