Lawson  Wehner

Lawson Wehner

1676601660

Check If A String is Empty in JavaScript

You can use the length property to check if a string is empty in JavaScript. If the string's length is equal to 0, then it is empty. Otherwise, the string is not empty.

const str = ''

if (str.length === 0) {
  console.log(`String is empty ✅`)
} else {
  console.log(`String is not empty ❌`)
}

// String is empty ✅

If the string contains leading or trailing whitespace, you should use the trim() method to remove whitespace before checking if it is empty:

const str = '   '

if (str.trim().length === 0) {
  console.log(`String is empty ✅`)
} else {
  console.log(`String is not empty ❌`)
}

// String is empty ✅

The trim() method removes the leading and trailing spaces from a string. It returns an empty string if the string only contains spaces.

Alternatively, you could also use the strict equality operator (===) to check whether a string is empty or not:

const str = ''

console.log(str === '')             // true
console.log(0 === '')               // false
console.log(false === '')           // false
console.log([] === '')              // false
console.log(null === '')            // false
console.log(undefined === '')       // false

As you can see above, the strict equality operator returns false for null, undefined, and false values in the comparison because these are special values.

To check if a string is truthy and contains one or more characters, use the following code:

const str = 'js'

if (str) {
  // `str` variable is NOT false, undefined,
  // null, empty string, NaN
  console.log(`String is truthy 💯`)
}

// String is truthy 💯

A variable is truthy if it is not an empty string, 0, null, undefined, false, or NaN.

Original article source at: https://attacomsian.com/

#javascript #string #empty 

Check If A String is Empty in JavaScript
Monty  Boehm

Monty Boehm

1676422800

Check if an Object is Empty in JavaScript

Check if an Object is Empty in JavaScript

Introduction

Objects are used to store a collection of properties, each of which may be thought of as an association between a name (or key) and a value (a collection of key-value pairs).

In this guide, we will explore many JavaScript methods on how to check if an object is empty. We'll be using Vanilla JavaScript, as well as common libraries such as lodash and underscore.

When it comes to small applications that don't require external dependencies - checking whether an object is empty is best done with pure JavaScript. However, if your application already has external libraries such as lodash and underscore - they offer great ways to perform these checks as well.

Checking if an object is empty or not is a basic and frequent operation, however, there are several methods for determining whether it's empty or not.

Let's start by creating an empty Object with the object literal syntax:

const emptyObject = {}

Using the Object.keys() Method

Object.keys() is a static method that returns an Array when we pass an object to it, which contains the property names (keys) belonging to that object. We can check whether the length of this array is 0 or higher - denoting whether any keys are present or not. If no keys are present, the object is empty:

Object.keys(obj).length === 0 && obj.constructor === Object;

Note: The constructor check makes sure the passed argument is indeed an object.

We could also create a reusable function, if you're using the check multiple times in the project:

const isEmptyObject = (obj) => {
    return Object.keys(obj).length === 0 && obj.constructor === Object;
}

console.log(isEmptyObject(emptyObject)); // true

This is by far the simplest method for determining whether an object is empty, though, it's a bit verbose. We'll remove this verbosity with following approaches - after we take a look at the Object.values() and Object.entries() static methods, which can be used in much the same way as Object.keys().

Using the Object.values() Method

Just as with keys - if an object has no values associated (not even an undefined/null) - it's empty:

const isEmptyObject = (obj) => {
    return Object.values(obj).length === 0 && obj.constructor === Object;
}

console.log(isEmptyObject(emptyObject)); // true

Using the Object.entries() Method

The entries() method represents all key-value pairs (entries), which can be used as a wrapper for both of the approaches above:

const isEmptyObject = (obj) => {
    return Object.entries(obj).length === 0 && obj.constructor === Object;
}

console.log(isEmptyObject(emptyObject)); // true

for...in and hasOwnProperty()

For browsers that don't support the keys(), values() and entries() methods - you can explicitly loop through the properties! You can wrap this logic within a method that returns true if no properties were found, and false if properties were found:

const isEmptyObject = (objectName) => {
    for (var prop in objectName) {
        if (objectName.hasOwnProperty(prop)) {
            return false;
        }
    }
    return true;
}

console.log(isEmptyObject(emptyObject)); // true

Using JSON.stringify

This is one of the simplest method to use. When we stringify an object and the output is only an opening and closing bracket, we know the item is empty:

JSON.stringify(objectName) === '{}';

We could also easily be wrapped into a function:

const isEmptyObject = (objectName) => {
    return JSON.stringify(objectName) === '{}';
}

console.log(isEmptyObject(emptyObject)); // true

Check if Object Is Empty With JavaScript Libraries

Libraries help us write code faster, by incorporating advanced functionality, used and honed by countless other developers, instead of writing our own solutions.

Libraries are common, typically fast/optimized, and some are present in many projects due to how useful they are. Several of them can also be used for checking whether an object is empty or not. The majority of them offer excellent compatibility for older browsers.

Using Underscore and Lodash

Both lodash and underscore are utility libraries that offer a fair bit of common utilities. They're both typically imported as _, and can be imported via a CDN:

<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/underscore@1.13.2/underscore-umd-min.js"></script>

Or installed a package manager such as NPM, and then imported via the require() syntax:

$ npm install lodash
$ npm install underscore
const _ = require('lodash');
const _ = require('underscore');

Both libraries have the exact same syntax for checking whether an object is empty:

_.isEmpty();

This function works with any data structure - lists, arrays, strings, objects, etc. The function is a wrapper around the logic that checks the length of the object that was passed in, returning true or false:

_.isEmpty(emptyObject); // true

jQuery

jQuery is a popular JavaScript library, present in many projects around the world. Due to its light weight and features that expand the scope of JavaScript's built-in capabilities - it's become a staple.

jQuery can be imported via a CDN:

<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>

Or installed a package manager such as NPM, and then imported via the require() syntax:

$ npm install jquery

It's typically imported as $:

const $ = require('jquery');

Naturally, you can use it to check whether an object is empty or not:

$.isEmptyObject(emptyObject); // true

Ramda

Ramda is a functional JavaScript library! It never mutates data and supports the creation of purely functional pipelines. For those with a more functional programming background - it's a great library to feel at home with.

Ramda can be imported via a CDN:

<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.28.0/ramda.min.js"></script>

Or installed a package manager such as NPM, and then imported via the require() syntax:

$ npm install ramda

It's typically imported as R:

const R = require('ramda');

If you're already using it - it offers an isEmpty() function as well:

R.isEmpty(emptyObject); // true

Hoek

@hapi/hoek is part of the hapi ecosystem, and a popular utility method library for hapi-based apps. It offers a deepEqual() method, that checks whether two objects are the same (depth-wise):

Hoek.deepEqual({}, emptyObject); // true

Conclusion

In this article, we have taken a look at how to check whether an object is empty or not in JavaScript. To this end - we've used several Vanilla JS approaches, jQuery, Underscore, Lodash, Ramda, Hoek and the JSON module.

Original article source at: https://stackabuse.com/

#javascript #empty #object 

Check if an Object is Empty in JavaScript
Rupert  Beatty

Rupert Beatty

1671656340

Guide to RxJS: defaultIfEmpty

tldr;

RxJS pipelines are convenient ways to get work done in your applications. You can essentially tell the app the steps it needs to take, and it will go step by step through the pipeline. But what if one of the steps will potentially be empty, but you want the pipeline to continue? That’s where the defaultIfEmpty operator can come in handy. I recently learned about it when I had a similar situation, and it worked perfectly for me.

Background

I was recently working on an application where you needed to be able to add, edit, and delete data. The work needed to be done in a certain order: deletions first, then additions or edits. This is straightforward as long as there are actions for each of the above types to be done: at least one add, one edit, and one delete. But what happens if one of those types doesn’t need to be done in a given pipeline?

This is the situation I found myself in. If the delete observable was empty, nothing happened. I needed the pipeline to continue, however, and move on to adds and edits. I started searching around and found the defaultIfEmpty operator, which solved my problem for me.

defaultIfEmpty

The defaultIfEmpty operator does exactly what it sounds like: it provides a default value in the pipeline if the preceding observable doesn’t emit a value. This ensures that the pipeline doesn’t get stuck, but instead outputs a value.

Let’s look at a couple examples. First we’ll look at an example pipeline where there is a type for adds, edits, and deletes.

const deletions = [of('delete 1')];
const additions = [of('add 1')];
const edits = [of('edit 1')];

zip(...deletions)
  .pipe(
    tap((deletionResult) => console.log(deletionResult)),
    switchMap(() => zip(...additions)),
    tap((additionResult) => console.log(additionResult)),
    switchMap(() => zip(...edits)),
    tap((editsResult) => console.log(editsResult))
  )
  .subscribe();

In the above example, this pipeline will execute as expected. The deletion observables will run and emit a value, then the additions, then the edits. The result of all three sections will be logged to the console. Easy enough, right? But what do we do if we have no deletions to run?

const deletions2 = [];
const additions2 = [of('add 2')];
const edits2 = [of('edit 2')];

zip(...deletions2)
  .pipe(
    tap((deletionResult) => console.log(deletionResult)),
    switchMap(() => zip(...additions2)),
    tap((additionResult) => console.log(additionResult)),
    switchMap(() => zip(...edits2)),
    tap((editsResult) => console.log(editsResult))
  )
  .subscribe();

In this example, nothing gets logged to the console. We never move past the first step, because nothing is ever emitted from the initial zip(...deletions2) portion of the pipeline. But just because we don’t have anything to delete doesn’t mean we don’t want to continue with adding and editing the other pieces. This is where the defaultIfEmpty operator comes in handy. Insert it after a given step in the observable pipeline that could potentially emit no data. Then the pipeline will continue. Continuing with the above example, we can change it to the following to get our pipeline working again.

zip(...deletions2)
  .pipe(
    defaultIfEmpty([]),
    tap((deletionResult) => console.log(deletionResult)),
    switchMap(() => zip(...additions2)),
    tap((additionResult) => console.log(additionResult)),
    switchMap(() => zip(...edits2)),
    tap((editsResult) => console.log(editsResult))
  )
  .subscribe();

Now our pipeline continues and values are logged to the console. The defaultIfEmpty([]) operator essentially says if the preceding observable doesn’t emit a value, emit an empty array and then continue on to the next step. So, although we don’t have anything to delete, we can still do our adds and edits.

Let’s look at one last example, where we have deletions and edits to do, but no additions. Can you guess what will happen?

const deletions3 = [of('delete3')];
const additions3 = [];
const edits3 = [of('edit 3')];

zip(...deletions3)
  .pipe(
    tap((deletionResult) => console.log(deletionResult)),
    switchMap(() => zip(...additions3)),
    tap((additionResult) => console.log(additionResult)),
    switchMap(() => zip(...edits3)),
    tap((editsResult) => console.log(editsResult))
  )
  .subscribe();

If you guessed nothing happens at all, you’re close. But it does finish the delete step before stopping. So your edits never occur. To fix the issue, we just need to add another defaultIfEmpty operator.

zip(...deletions3)
  .pipe(
    tap((deletionResult) => console.log(deletionResult)),
    switchMap(() => zip(...additions3).pipe(defaultIfEmpty([]))),
    tap((additionResult) => console.log(additionResult)),
    switchMap(() => zip(...edits3)),
    tap((editsResult) => console.log(editsResult))
  )
  .subscribe();

Note: You can add the defaultIfEmpty operator in the pipe for the additions like I have above, or you can add it directly after the switchMap; either way will work.

With this minor change to our pipeline, it now finishes as we expect. The deletions are made, followed by the edits.

Conclusion

I was initially stuck with figuring out how to make sure my pipeline continued, even if there was an empty step in the pipeline. But I should have known there was an operator to help me out. There are a lot of operators, and while it makes RxJS seem overwhelming at first it’s also very convenient for situations like this. When you get stuck, ask for help and read the docs. You’re likely to find someone who’s run into the same problem and can point you in the right direction.

Here’s a StackBlitz with the examples we looked at above.

Original article source at: https://www.prestonlamb.com/

#rxjs #empty 

Guide to RxJS: defaultIfEmpty
Monty  Boehm

Monty Boehm

1670937608

How to On-demand Reactivity in Vue 3

The release of Vue 3 brought about substantial performance improvements, but they should not overshadow the introduction of new features and paradigms. In this article, Toptal Full-stack Developer Luka Mikec introduces you to the new Composition API and explains what Vue 3 means for code expressiveness, organization, and reuse.

Apart from admirable performance improvements, the recently released Vue 3 also brought several new features. Arguably the most important introduction is the Composition API. In the first part of this article, we recap the standard motivation for a new API: better code organization and reuse. In the second part, we will focus on less-discussed aspects of using the new API, such as implementing reactivity-based features that were inexpressible in Vue 2’s reactivity system.

We will refer to this as on-demand reactivity. After introducing the relevant new features, we will build a simple spreadsheet application to demonstrate the new expressiveness of Vue’s reactivity system. At the very end, we will discuss what real-world use this improvement on-demand reactivity might have.

What’s New in Vue 3 and Why it Matters

Vue 3 is a major rewrite of Vue 2, introducing a plethora of improvements while retaining backward compatibility with the old API almost in its entirety.

One of the most significant new features in Vue 3 is the Composition API. Its introduction sparked much controversy when it was first discussed publicly. In case you are not already familiar with the new API, we will first describe the motivation behind it.

The usual unit of code organization is a JavaScript object whose keys represent various possible types of a piece of a component. Thus the object might have one section for reactive data (data), another section for computed properties (computed), one more for component methods (methods), etc.

Under this paradigm, a component can have multiple unrelated or loosely related functionalities whose inner workings are distributed among the aforementioned component sections. For example, we might have a component for uploading files that implements two essentially separate functionalities: file management and a system that controls the upload status animation.

The <script> portion might contain something like the following:

export default {
  data () {
    return {
      animation_state: 'playing', 
      animation_duration: 10,
      upload_filenames: [],
      upload_params: {
        target_directory: 'media',
        visibility: 'private',
      }
    }
  },
  computed: {
    long_animation () { return this.animation_duration > 5; }, 
    upload_requested () { return this.upload_filenames.length > 0; }, 
  },
  ...
}

There are benefits to this traditional approach to code organization, mainly in the developer not having to worry about where to write a new piece of code. If we’re adding a reactive variable, we insert it in the data section. If we’re looking for an existing variable, we know it must be in the data section.

This traditional approach of splitting the functionality’s implementation into sections (data, computed, etc.) is not suitable in all situations.

The following exceptions are cited often:

  1. Dealing with a component with a large number of functionalities. If we want to upgrade our animation code with the ability to delay the start of the animation, for example, we will have to scroll/jump between all the relevant sections of the component in a code editor. In the case of our file-uploading component, the component itself is small and the number of functionalities it implements is small, too. Thus, in this case, jumping between the sections is not really a problem. This issue of code fragmentation becomes relevant when we deal with large components.
  2. Another situation where the traditional approach is lacking is code reuse. Often we need to make a specific combination of reactive data, computed properties, methods, etc., available in more than one component.

Vue 2 (and the backward-compatible Vue 3) offer a solution to most of the code organization and reuse issues: mixins.

Pros and Cons of Mixins in Vue 3

Mixins allow the functionalities of a component to be extracted in a separate unit of code. Each functionality is put in a separate mixin and every component can use one or more mixins. Pieces defined in a mixin can be used in a component as if they were defined in the component itself. The mixins are a bit like classes in object-oriented languages in that they collect the code related to a given functionality. Like classes, mixins can be inherited (used) in other units of code.

However, reasoning with mixins is harder since, unlike classes, mixins need not be designed with encapsulation in mind. Mixins are allowed to be collections of loosely bound pieces of code without a well-defined interface to the outer world. Using more than one mixin at a time in the same component might result in a component that is difficult to comprehend and use.

Most object-oriented languages (e.g., C# and Java) discourage or even disallow multiple inheritance despite the fact that the object-oriented programming paradigm has the tools to deal with such complexity. (Some languages do allow multiple inheritance, such as C++, but composition is still preferred over inheritance.)

A more practical issue that may occur when using mixins in Vue is name collision, which occurs when using two or more mixins declaring common names. It should be noted here that if Vue’s default strategy for dealing with name collisions is not ideal in a given situation, the strategy can be adjusted by the developer.This comes at the cost of introducing more complexity.

Another issue is that mixins do not offer something akin to a class constructor. This is a problem because often we need functionality that is very similar, but not exactly the same, to be present in different components. This can be circumvented in some simple cases with the use of mixin factories.

Therefore, mixins are not the ideal solution for code organization and reuse, and the larger the project, the more serious their issues become. Vue 3 introduces a new way of solving the same issues concerning code organization and reuse.

Composition API: Vue 3’s Answer to Code Organisation and Reuse

The Composition API allows us (but does not require us) to completely decouple the pieces of a component. Every piece of code—a variable, a computed property, a watch, etc.—can be defined independently.

For example, instead of having an object that contains a data section that contains a key animation_state with the (default) value “playing,” we can now write (anywhere in our JavaScript code):

const animation_state = ref('playing');

The effect is almost the same as declaring this variable in the data section of some component. The only essential difference is that we need to make the ref defined outside of the component available in the component where we intend to use it. We do this by importing its module to the place where the component is defined and return the ref from the setup section of a component. We’ll skip this procedure for now and just focus on the new API for a moment. Reactivity in Vue 3 doesn’t require a component; it’s actually a self-contained system.

We can use the variable animation_state in any scope that we import this variable to. After constructing a ref, we get and set its actual value using ref.value, for example:

animation_state.value = 'paused';
console.log(animation_state.value);

We need the ‘.value’ suffix since the assignment operator would otherwise assign the (non-reactive) value “paused” to the variable animation_state. Reactivity in JavaScript (both when it is implemented through the defineProperty as in Vue 2, and when it’s based on a Proxy as in Vue 3) requires an object whose keys we can work with reactively.

Note that this was the case in Vue 2, as well; there, we had a component as a prefix to any reactive data member (component.data_member). Unless and until the JavaScript language standard introduces the ability to overload the assignment operator, reactive expressions will require an object and a key (e.g., animation_state and value as above) to appear on the left-hand side of any assignment operation where we wish to preserve reactivity.

In templates, we can omit .value since Vue has to preprocess the template code and can automatically detect references:

<animation :state='animation_state' />

In theory, the Vue compiler could preprocess the <script> portion of a Single File Component (SFC) in a similar way, too, inserting .value where needed. However, the use of refs would then differ based on whether we are using SFCs or not, so perhaps such a feature is not even desirable.

Sometimes, we have an entity (for example, be a Javascript object or an array) that we never intend to replace with a completely different instance. Instead, we might only be interested in modifying its keyed fields. There is a shorthand in this case: using reactive instead of ref allows us to dispense with the .value:

const upload_params = reactive({
  target_directory: 'media',
  visibility: 'private',
});

upload_params.visibility = 'public';    // no `.value` needed here

// if we did not make `upload_params` constant, the following code would compile but we would lose reactivity after the assignment; it is thus a good idea to make reactive variables ```const``` explicitly:
upload_params = {
  target_directory: 'static',
  visibility: 'public',
};

Decoupled reactivity with ref and reactive is not a completely new feature of Vue 3. It was partly introduced in Vue 2.6, where such decoupled instances of reactive data were called “observables.” For the most part, one can replace Vue.observable with reactive. One of the differences is that accessing and mutating the object passed to Vue.observable directly is reactive, while the new API returns a proxy object, so mutating the original object will not have reactive effects.

Comparison: Options API vs. Composition API.

What is completely new in Vue 3 is that other reactive pieces of a component can now be defined independently too, in addition to reactive data. Computed properties are implemented in an expected way:

const x = ref(5);
const x_squared = computed(() => x.value * x.value);
console.log(x_squared.value); // outputs 25

Similarly one can implement various types of watches, lifecycle methods, and dependency injection. For the sake of brevity, we won’t cover those here.

Suppose we use the standard SFC approach to Vue development. We might even be using the traditional API, with separate sections for data, computed properties, etc. How do we integrate the Composition API’s small bits of reactivity with SFCs? Vue 3 introduces another section just for this: setup. The new section can be thought of as a new lifecycle method (which executes before any other hook—in particular, before created).

Here is an example of a complete component that integrates the traditional approach with the Composition API:

<template>
  <input v-model="x" />
  <div>Squared: {{ x_squared }}, negative: {{ x_negative }}</div>
</template>

<script>
import { ref, computed } from 'vue';

export default {
  name: "Demo",
  computed: {
    x_negative() { return -this.x; }
  },
  setup() {
    const x = ref(0);
    const x_squared = computed(() => x.value * x.value);
    return {x, x_squared};
  }
}
</script>

Things to take away from this example:

  • All the Composition API code is now in setup. You might want to create a separate file for each functionality, import this file in an SFC, and return the desired bits of reactivity from setup (to make them available to the remainder of the component).
  • You can mix the new and the traditional approach in the same file. Notice that x, even though it’s a reference, does not require .value when referred to in the template code or in traditional sections of a component such as computed.
  • Last but not least, notice we have two root DOM nodes in our template; the ability to have multiple root nodes is another new feature of Vue 3.

Reactivity is More Expressive in Vue 3

In the first part of this article, we touched upon the standard motivation for the Composition API, which is improved code organization and reuse. Indeed, the new API’s main selling point is not its power, but the organizational convenience that it brings: the ability to structure the code more clearly. It might seem like that is all—that the Composition API enables a way of implementing components that avoids the limitations of the already existing solutions, such as mixins.

However, there is more to the new API. The Composition API actually enables not just better organized but more powerful reactive systems. The key ingredient is the ability to dynamically add reactivity to the application. Previously, one had to define all the data, all the computed properties, etc. before loading a component. Why would adding reactive objects at a later stage be useful? In what remains we take a look at a more complex example: spreadsheets.

Creating a Spreadsheet in Vue 2

Spreadsheet tools such as Microsoft Excel, LibreOffice Calc, and Google Sheets all have some sort of a reactivity system. These tools present a user with a table, with columns indexed by A–Z, AA–ZZ, AAA–ZZZ, etc., and rows indexed numerically.

Each cell may contain a plain value or a formula. A cell with a formula is essentially a computed property, which may depend on values or other computed properties. With standard spreadsheets (and unlike the reactivity system in Vue), these computed properties are even allowed to depend on themselves! Such self-reference is useful in some scenarios where the desired value is obtained by iterative approximation.

Once a cell’s content changes, all the cells that depend on the cell in question will trigger an update. If further changes occur, further updates might be scheduled.

If we were to build a spreadsheet application with Vue, it would be natural to ask if we can put Vue’s own reactivity system to use and make Vue the engine of a spreadsheet app. For each cell, we could remember its raw editable value, as well as the corresponding computed value. Computed values would reflect the raw value if it’s a plain value, and otherwise, the computed values are the result of the expression (formula) that is written instead of a plain value.

With Vue 2, a way to implement a spreadsheet is to have raw_values a two-dimensional array of strings, and computed_values a (computed) two-dimensional array of cell values.

If the number of cells is small and fixed before the appropriate Vue component loads, we could have one raw and one computed value for every cell of the table in our component definition. Aside from the aesthetic monstrousness that such an implementation would cause, a table with a fixed number of cells at compile-time probably doesn’t count as a spreadsheet.

There are problems with the two-dimensional array computed_values, too. A computed property is always a function whose evaluation, in this case, depends on itself (calculating the value of a cell will, in general, require some other values to already be computed). Even if Vue allowed self-referential computed properties, updating a single cell would cause all cells to be recomputed (regardless of whether there are dependencies or not). This would be extremely inefficient. Thus, we might end up using reactivity to detect changes in the raw data with Vue 2, but everything else reactivity-wise would have to be implemented from scratch.

Modeling Computed Values in Vue 3

With Vue 3, we can introduce a new computed property for every cell. If the table grows, new computed properties are introduced.

Suppose we have cells A1 and A2, and we wish for A2 to display the square of A1 whose value is the number 5. A sketch of this situation:

let A1 = computed(() => 5);
let A2 = computed(() => A1.value * A1.value);
console.log(A2.value); // outputs 25

Suppose we stay in this simple scenario for a moment. There is an issue here; what if we wish to change A1 so that it contains the number 6? Suppose we write this:

A1 = computed(() => 6);
console.log(A2.value); // outputs 25 if we already ran the code above

This didn’t merely change the value 5 to 6 in A1. The variable A1 has a completely different identity now: the computed property that resolves to the number 6. However, the variable A2 still reacts to changes of the old identity of the variable A1. So, A2 shouldn’t refer to A1 directly, but rather to some special object that will always be available in the context, and will tell us what is A1 at the moment. In other words, we need a level of indirection before accessing A1, something like a pointer. There are no pointers as first-class entities in Javascript, but it’s easy to simulate one. If we wish to have a pointer pointing to a value, we can create an object pointer = {points_to: value}. Redirecting the pointer amounts to assigning to pointer.points_to, and dereferencing (accessing the pointed-to value) amounts to retrieving the value of pointer.points_to. In our case we proceed as follows:

let A1 = reactive({points_to: computed(() => 5)});
let A2 = reactive({points_to: computed(() => A1.points_to * A1.points_to)});
console.log(A2.points_to); // outputs 25

Now we can substitute 5 with 6.

A1.points_to = computed(() => 6);
console.log(A2.points_to); // outputs 36

On Vue’s Discord server, the user redblobgames suggested another interesting approach: instead of using computed values, use references that wrap regular functions. This way, one can similarly swap the function without changing the identity of the reference itself.

Our spreadsheet implementation will have cells referred to by keys of some two-dimensional array. This array can provide the level of indirection we require. Thus in our case, we won’t require any additional pointer simulation. We could even have one array that does not distinguish between raw and computed values. Everything can be a computed value:

const cells = reactive([
  computed(() => 5),
  computed(() => cells[0].value * cells[0].value)
]);

cells[0] = computed(() => 6);
console.log(cells[1].value); // outputs 36

However, we really want to distinguish raw and computed values since we want to be able to bind the raw value to an HTML input element. Furthermore, if we have a separate array for raw values, we never have to change the definitions of computed properties; they will update automatically based on the raw data.

Implementing the Spreadsheet

Let’s start with some basic definitions, which are for the most part self-explanatory.

const rows = ref(30), cols = ref(26);

/* if a string codes a number, return the number, else return a string */
const as_number = raw_cell => /^[0-9]+(\.[0-9]+)?$/.test(raw_cell)  
    ?  Number.parseFloat(raw_cell)  :  raw_cell;

const make_table = (val = '', _rows = rows.value, _cols = cols.value) =>
    Array(_rows).fill(null).map(() => Array(_cols).fill(val));

const raw_values = reactive(make_table('', rows.value, cols.value));
const computed_values = reactive(make_table(undefined, rows.value, cols.value));

/* a useful metric for debugging: how many times did cell (re)computations occur? */
const calculations = ref(0);

The plan is for every computed_values[row][column] to be computed as follows. If raw_values[row][column] doesn’t start with =, return raw_values[row][column]. Otherwise, parse the formula, compile it to JavaScript, evaluate the compiled code, and return the value. To keep things short, we’ll cheat a bit with parsing formulas and we won’t do some obvious optimizations here, such as a compilation cache.

We will assume that users can enter any valid JavaScript expression as a formula. We can replace references to cell names that appear in user’s expressions, such as A1, B5, etc., with the reference to the actual cell value (computed). The following function does this job, assuming that strings resembling cell names really always identify cells (and are not a part of some unrelated JavaScript expression). For simplicity, we will assume column indices consist of a single letter.

const letters = Array(26).fill(0)
    .map((_, i) => String.fromCharCode("A".charCodeAt(0) + i));

const transpile = str => {
    let cell_replacer = (match, prepend, col, row) => {
        col = letters.indexOf(col);
        row = Number.parseInt(row) - 1;
        return prepend + ` computed_values[${row}][${col}].value `;
    };
    return str.replace(/(^|[^A-Z])([A-Z])([0-9]+)/g, cell_replacer);
};

Using the transpile function, we can get pure JavaScript expressions out of expressions written in our little “extension” of JavaScript with cell references.

The next step is to generate computed properties for every cell. This procedure will occur once in the lifetime of every cell. We can make a factory that will return the desired computed properties:

const computed_cell_generator = (i, j) => {
    const computed_cell = computed(() => {
        // we don't want Vue to think that the value of a computed_cell depends on the value of `calculations`
        nextTick(() => ++calculations.value);
      
        let raw_cell = raw_values[i][j].trim();
        if (!raw_cell || raw_cell[0] != '=') 
            return as_number(raw_cell);
      
        let user_code = raw_cell.substring(1);
        let code = transpile(user_code);
        try {
            // the constructor of a Function receives the body of a function as a string
            let fn = new Function(['computed_values'], `return ${code};`);
            return fn(computed_values);
        } catch (e) {
            return "ERROR";
        }
    });
    return computed_cell;
};

for (let i = 0; i < rows.value; ++i)
    for (let j = 0; j < cols.value; ++j)
        computed_values[i][j] = computed_cell_generator(i, j);

If we put all of the code above in the setup method, we need to return {raw_values, computed_values, rows, cols, letters, calculations}.

Below, we present the complete component, together with a basic user interface.

The code is available on GitHub, and you can also check out the live demo.

<template>
  <div>
    <div style="margin: 1ex;">Calculations: {{ calculations }}</div>
    <table class="table" border="0">
      <tr class="row">
        <td id="empty_first_cell"></td>

        <td class="column"
            v-for="(_, j) in cols" :key="'header' + j"
        >
          {{ letters[j] }}
        </td>
      </tr>

      <tr class="row"
          v-for="(_, i) in rows" :key="i"
      >
        <td class="column">
          {{ i + 1 }}
        </td>

        <td class="column"
            v-for="(__, j) in cols" :key="i + '-' + j"
            :class="{ column_selected: active(i, j), column_inactive: !active(i, j),  }"
            @click="activate(i, j)"
        >
          <div v-if="active(i, j)">
            <input :ref="'input' + i + '-' + j"
                   v-model="raw_values[i][j]"
                   @keydown.enter.prevent="ui_enter()"
                   @keydown.esc="ui_esc()"
            />
          </div>
          <div v-else v-html="computed_value_formatter(computed_values[i][j].value)"/>
        </td>
      </tr>
    </table>
  </div>
</template>

<script>
import {ref, reactive, computed, watchEffect, toRefs, nextTick, onUpdated} from "vue";

export default {
  name: 'App',
  components: {},
  data() {
    return {
      ui_editing_i: null,
      ui_editing_j: null,
    }
  },
  methods: {
    get_dom_input(i, j) {
      return this.$refs['input' + i + '-' + j];
    },
    activate(i, j) {
      this.ui_editing_i = i;
      this.ui_editing_j = j;
      nextTick(() => this.get_dom_input(i, j).focus());
    },
    active(i, j) {
      return this.ui_editing_i === i && this.ui_editing_j === j;
    },
    unselect() {
      this.ui_editing_i = null;
      this.ui_editing_j = null;
    },
    computed_value_formatter(str) {
      if (str === undefined || str === null)
        return 'none';
      return str;
    },
    ui_enter() {
      if (this.ui_editing_i < this.rows - 1)
        this.activate(this.ui_editing_i + 1, this.ui_editing_j);
      else
        this.unselect();
    },
    ui_esc() {
      this.unselect();
    },
  },
  setup() {

    /*** All the code we wrote above goes here. ***/

    return {raw_values, computed_values, rows, cols, letters, calculations};
  },
}
</script>

<style>
.table {
  margin-left: auto;
  margin-right: auto;
  margin-top: 1ex;
  border-collapse: collapse;
}

.column {
  box-sizing: border-box;
  border: 1px lightgray solid;
}

.column:first-child {
  background: #f6f6f6;
  min-width: 3em;
}

.column:not(:first-child) {
  min-width: 4em;
}

.row:first-child {
  background: #f6f6f6;
}

#empty_first_cell {
  background: white;
}

.column_selected {
  border: 2px cornflowerblue solid !important;
  padding: 0px;
}

.column_selected input, .column_selected input:active, .column_selected input:focus {
  outline: none;
  border: none;
}
</style>

What About Real-world Use?

We saw how the decoupled reactivity system of Vue 3 enables not only cleaner code but allows more complex reactive systems based on the Vue’s new reactivity mechanism. Roughly seven years have passed since Vue was introduced, and the rise in expressiveness was clearly not highly sought after.

The spreadsheet example is a straightforward demonstration of what Vue is capable of now, and you can also check out the live demo.

But as a real-word example, it is somewhat niche. In what sort of situations might the new system come in handy? The most obvious use-case for on-demand reactivity might be in performance gains for complex applications.

Vue 2 vs Vue 3 funnel comparison.

In front-end applications that work with a large amount of data, the overhead of using poorly thought-through reactivity might have a negative impact on performance. Suppose we have a business dashboard application that produces interactive reports of the company’s business activity. The user can select a time range and add or remove performance indicators in the report. Some indicators may display values that depend on other indicators.

One way to implement report generation is through a monolithic structure. When the user changes an input parameter in the interface, a single computed property, e.g., report_data, gets updated. The computation of this computed property happens according to a hardcoded plan: first, calculate all the independent performance indicators, then those that depend only on these independent indicators, etc.

A better implementation will decouple bits of the report and compute them independently. There are some benefits to this:

  • The developer does not have to hardcode an execution plan, which is tedious and error-prone. Vue’s reactivity system will automatically detect dependencies.
  • Depending on the amount of data involved, we might get substantial performance gains since we are only updating the report data that logically depended on the modified input parameters.

If all performance indicators that may be a part of the final report are known before the Vue component gets loaded, we may be able to implement the proposed decoupling even with Vue 2. Otherwise, if the backend is the single source of truth (which is usually the case with data-driven applications), or if there are external data providers, we can generate on-demand computed properties for every piece of a report.

Thanks to Vue 3, this is now not only possible but easy to do.

Original article source at: https://www.toptal.com/

#vue 

How to On-demand Reactivity in Vue 3
Rupert  Beatty

Rupert Beatty

1666950180

Placeholder Views Based on Content, Loading, Error Or Empty States

StatefulViewController

A protocol to enable UIViewControllers or UIViews to present placeholder views based on content, loading, error or empty states.

StatefulViewController Example

Overview

In a networked application a view controller or custom view typically has the following states that need to be communicated to the user:

  • Loading: The content is currently loaded over the network.
  • Content: The content is available and presented to the user.
  • Empty: There is currently no content available to display.
  • Error: An error occurred whilst downloading content.

As trivial as this flow may sound, there are a lot of cases that result in a rather large decision tree.

Decision Tree

StatefulViewController is a concrete implementation of this particular decision tree. (If you want to create your own modified version, you might be interested in the state machine that is used to show and hide views.)

Version Compatibility

Current Swift compatibility breakdown:

Swift VersionFramework Version
3.03.x
2.32.x
2.21.x

Usage

This guide describes the use of the StatefulViewController protocol on UIViewController. However, you can also adopt the StatefulViewController protocol on any UIViewController subclass, such as UITableViewController or UICollectionViewController, as well as your custom UIView subclasses.

First, make sure your view controller adopts to the StatefulViewController protocol.

class MyViewController: UIViewController, StatefulViewController {
    // ...
}

Then, configure the loadingView, emptyView and errorView properties (provided by the StatefulViewController protocol) in viewDidLoad.

override func viewDidLoad() {
    super.viewDidLoad()

    // Setup placeholder views
    loadingView = // UIView
    emptyView = // UIView
    errorView = // UIView
}

In addition, call the setupInitialViewState() method in viewWillAppear: in order to setup the initial state of the controller.

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    setupInitialViewState()
}

After that, simply tell the view controller whenever content is loading and StatefulViewController will take care of showing and hiding the correct loading, error and empty view for you.

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    loadDeliciousWines()
}

func loadDeliciousWines() {
    startLoading()

    let url = NSURL(string: "http://example.com/api")
    let session = NSURLSession.sharedSession()
    session.dataTaskWithURL(url) { (let data, let response, let error) in
        endLoading(error: error)
    }.resume()
}

Life cycle

StatefulViewController calls the hasContent method to check if there is any content to display. If you do not override this method in your own class, StatefulViewController will always assume that there is content to display.

func hasContent() -> Bool {
    return datasourceArray.count > 0
}

Optionally, you might also be interested to respond to an error even if content is already shown. StatefulViewController will not show its errorView in this case, because there is already content that can be shown.

To e.g. show a custom alert or other unobtrusive error message, use handleErrorWhenContentAvailable: to manually present the error to the user.

func handleErrorWhenContentAvailable(error: ErrorType) {
    let alertController = UIAlertController(title: "Ooops", message: "Something went wrong.", preferredStyle: .Alert)
    alertController.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
    presentViewController(alertController, animated: true, completion: nil)
}

Custom Placeholder View insets

Per default, StatefulViewController presents all configured placeholder views fullscreen (i.e. with 0 insets from top, bottom, left & right from the superview). In case a placeholder view should have custom insets the configured placeholderview may conform to the StatefulPlaceholderView protocol and override the placeholderViewInsets method to return custom edge insets.

class MyPlaceholderView: UIView, StatefulPlaceholderView {
    func placeholderViewInsets() -> UIEdgeInsets {
        return UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)
    }
}

 

View State Machine

Note: The following section is only intended for those, who want to create a stateful controller that differs from the flow described above.

You can also use the underlying view state machine to create a similar implementation for your custom flow of showing/hiding views.

let stateMachine = ViewStateMachine(view: view)

// Add states
stateMachine["loading"] = loadingView
stateMachine["other"] = otherView

// Transition to state
stateMachine.transitionToState(.View("loading"), animated: true) {
    println("finished switching to loading view")
}

// Hide all views
stateMachine.transitionToState(.None, animated: true) {
    println("all views hidden now")
}

Installation

Carthage

Add the following line to your Cartfile.

github "aschuch/StatefulViewController" ~> 3.0

Then run carthage update.

CocoaPods

Add the following line to your Podfile.

pod "StatefulViewController", "~> 3.0"

Then run pod install with CocoaPods 0.36 or newer.

Manually

Just drag and drop the two .swift files in the StatefulViewController folder into your project.

Tests

Open the Xcode project and press ⌘-U to run the tests.

Alternatively, all tests can be run from the terminal using xctool.

xctool -scheme StatefulViewControllerTests -sdk iphonesimulator test

Todo

  • Default loading, error, empty views
  • Protocol on views that notifies them of removal and add
  • Views can provide delays in order to tell the state machine to show/remove them only after a specific delay (e.g. for hide and show animations)

Contributing

  • Create something awesome, make the code better, add some functionality, whatever (this is the hardest part).
  • Fork it
  • Create new branch to make your changes
  • Commit all your changes to your branch
  • Submit a pull request

Contact

Feel free to get in touch.

Download Details:

Author: Aschuch
Source Code: https://github.com/aschuch/StatefulViewController  
License: MIT license

#swift #state #management #loading #error #empty 

Placeholder Views Based on Content, Loading, Error Or Empty States

Postgres.jl: Postgres Database interface for The Julia Language

Postgres

Postgres Database Interface for the Julia language.

Basic Usage

julia> using Postgres
julia> conn = connect(PostgresServer, db="julia_test", host="localhost")
julia> #conn = connect(PostgresServer, "postgresql://localhost/julia_test")
julia> #empty strings will cause the server to use defaults.
julia> #connect(interface, user, db, host, passwd, port)
julia> #conn = connect(PostgresServer, "", "julia_test", "localhost", "", "")
julia> curs = cursor(conn)
julia> df = query(curs, "select 1 from generate_series(1,5) as s")
5x1 DataFrames.DataFrame
| Row | x1 |
|-----|----|
| 1   | 1  |
| 2   | 1  |
| 3   | 1  |
| 4   | 1  |
| 5   | 1  |

Iteration

Memory management is automatic for the cursor interface.

Buffered (Normal) Cursor

julia> execute(curs, "select 1 from generate_series(1, 10)")
julia> for res in curs; println(res); end;
10x1 DataFrames.DataFrame
| Row | x1 |
|-----|----|
| 1   | 1  |
| 2   | 1  |
| 3   | 1  |
| 4   | 1  |
| 5   | 1  |
| 6   | 1  |
| 7   | 1  |
| 8   | 1  |
| 9   | 1  |
| 10  | 1  |
julia> for res in curs; println(res); end;
# nothing (memory already freed from server)

Streamed (Paged) Cursor

julia> streamed = cursor(conn, 3)
julia> execute(streamed, "select 1 from generate_series(1, 10)")
julia> for res in streamed; println(res); end;
3x1 DataFrames.DataFrame
| Row | x1 |
|-----|----|
| 1   | 1  |
| 2   | 1  |
| 3   | 1  |
3x1 DataFrames.DataFrame
| Row | x1 |
|-----|----|
| 1   | 1  |
| 2   | 1  |
| 3   | 1  |
3x1 DataFrames.DataFrame
| Row | x1 |
|-----|----|
| 1   | 1  |
| 2   | 1  |
| 3   | 1  |
1x1 DataFrames.DataFrame
| Row | x1 |
|-----|----|
| 1   | 1  |
0x1 DataFrames.DataFrame

Each iteration allocs and frees memory.

Result Interface

Cursor must be closed (or unreachable) to release server resources.

julia> using Postgres.Results
julia> result = execute(curs, "select 1, null::int, 'HI'::text, 1.2::float8  
            from generate_series(1, 5)")
5x4{Int32, Int32, UTF8String, Float64} PostgresResult
julia> result[1,1]     # array
Nullable(1)

julia> result[1, :]    # row; also row(curs, 1)
4-element Array{Any,1}:
 Nullable(1)      
 Nullable{Int32}()
 Nullable("HI")   
 Nullable(1.2) 

# columns are a lot faster to create
julia> result[:, 1]    # columns; also column(curs, 1)
5-element DataArrays.DataArray{Int32,1}:
 1
 1
 1
 1
 1
#row iteration
julia> for row in result; println(row); end
Any[Nullable(1),Nullable{Int32}(),Nullable("HI"),Nullable(1.2)]
# ...
close(curs) # free postgres resources

Transactions

julia> begin_!(curs)
INFO: BEGIN 
julia> rollback!(curs)
INFO: ROLLBACK 
julia> commit!(curs)
WARNING: WARNING:  there is no transaction in progress
INFO: COMMIT 
# transaction already ended by rollback

Base Types supported as Julia Types:

julia> for v in values(Postgres.Types.base_types)
            println(v)
       end

text -> UTF8String
varchar -> UTF8String
bpchar -> UTF8String
unknown -> UTF8String
bit -> BitArray{1}
varbit -> BitArray{1}
bytea -> Array{UInt8,1}
bool -> Bool
int2 -> Int16
int4 -> Int32
int8 -> Int64
float4 -> Float32
float8 -> Float64
numeric -> BigFloat
date -> Date
json -> UTF8String
jsonb -> UTF8String

Others supported as UTF8String.

Extended Types

Automatically determined on connection start up.

julia> types = collect(values(conn.pgtypes))
julia> enum_test = filter(x->x.name==:enum_test, types)[1]
enum_test ∈ Set(UTF8String["happy","sad"])
# pg def:
# Schema │   Name    │ Internal name │ Size │ Elements │
#────────┼───────────┼───────────────┼──────┼──────────┼
# public │ enum_test │ enum_test     │ 4    │ happy   ↵│
#        │           │               │      │ sad      │

julia> domain_test = filter(x->x.name==:domain_test, types)[1]
(domain_test <: int4) -> Int32
# pg def:
# Schema │    Name     │  Type   │ Modifier │               Check                │
#────────┼─────────────┼─────────┼──────────┼────────────────────────────────────┼
# public │ domain_test │ integer │          │ CHECK (VALUE >= 0 AND VALUE <= 10) │

Enum types will use PooledDataArrays!

Escaping

julia> user_input="1';select 'powned';"
julia> escape_value(conn, user_input)
"'1'';select ''powned'';'"

Error Info

julia> try query(curs, "select xxx")
        catch err PostgresServerError
           println(err.info)
       end
PostgresResultInfo(
            msg:ERROR:  column "xxx" does not exist
LINE 1: select xxx
               ^
            severity:ERROR
            state:syntax_error_or_access_rule_violation
            code:42703
            primary:column "xxx" does not exist
            detail:
            hint:
            pos:8
)

see Appendix A. in the Postgres manual for error code/state lists.

Copy Support

# Commands use the same interface as selects.
# Messages are passed through to Julia as you are used to seeing them in psql.
julia> println(query(curs, """
    drop table if exists s; 
    drop table if exists news; 
    create table s as select 1 as ss from generate_series(1,10)"""))
NOTICE:  table "news" does not exist, skipping
INFO: SELECT 10 10
0x0 DataFrames.DataFrame

julia> df = query(curs, "select * from s")
julia> copyto(curs, df, "s")
INFO: COPY 10 10
0x0{} PostgresResult

julia> copyto(curs, df, "news", true)
INFO: table 'news' not found in database. creating ...
INFO: CREATE TABLE 
INFO: COPY 10 10
0x0{} PostgresResult

Custom Types

julia> using Postgres.Types

julia> type Point
        x::Float64
        y::Float64
       end

# find the oid (600 in this case) in the pg_type table in Postgres.
# Then instance the type.
julia> base_types[600] = PostgresType{Point}(:point, Point(0, 0))
point -> Point

# create the _in_ function from the database
julia> function Postgres.Types.unsafe_parse{T <: Point}(::PostgresType{T}, value::UTF8String)
    x, y = split(value, ",")
    x = parse(Float64, x[2:end])
    y = parse(Float64, y[1:end-1])
    Point(x, y)
end
unsafe_parse (generic function with 15 methods)

# create the _out_ function to the database
julia> Postgres.Types.PostgresValue{T <: Point}(val::T) =
    Postgres.Types.PostgresValue{T}(base_types[600], "($(val.x),$(val.y))")
Postgres.Types.PostgresValue

#reload conn so it picks up the new type
julia> close(conn)
PostgresConnection(@ 0 : not_connected)
julia> conn = connect(PostgresServer, db="julia_test", host="localhost")
PostgresConnection(@ 0x0b41b818 : ok)
julia> curs = cursor(conn)
Postgres.BufferedPostgresCursor(
    PostgresConnection(@ 0x0b41b818 : ok),
    Nullable{Postgres.Results.PostgresResult}())

julia> p1 = Point(1.1, 1.1)
Point(1.1,1.1)
julia> start = repr(PostgresValue(p1))
"'(1.1,1.1)'::point"
julia> p2 = query(curs, "select $start")[1][1]
Point(1.1,1.1)
julia> p1.x == p2.x && p1.y == p2.y
true

Control-C cancels the query at the server

julia> query(curs, "select 1 from generate_series(1, (10^9)::int)")
# oops; this will take forever
^CINFO: canceling statement due to user request
ERROR: PostgresError: No results to fetch
 in fetch at /home/xxx/.julia/v0.4/Postgres/src/postgres.jl:383
  in query at /home/xxx/.julia/v0.4/Postgres/src/postgres.jl:405

#no need to chase down zombie process with ps or top :) :)

Download Details:

Author: NCarson
Source Code: https://github.com/NCarson/Postgres.jl 
License: View license

#julia #postgres 

Postgres.jl: Postgres Database interface for The Julia Language
Gordon  Taylor

Gordon Taylor

1657221960

Level-temp: Create A Temporary Sublevel That Is Guaranteed to Be Empty

level-temp

Create a temporary sublevel that is guaranteed to be empty.

npm install level-temp

Usage

var temp = require('level-temp')
var tmp = temp(db) // where db is a levelup

// call tmp to get a temporary sublevel that is empty

var a = tmp()

a.put('hello', 'world', function () {
  a.createReadStream()
    .on('data', function (data) {
      console.log('a has only one', data)
    })
})

// call tmp again to get another empty sublevel
var b = tmp()

b.put('hej', 'verden', function () {
  b.createReadStream()
    .on('data', function (data) {
      console.log('b has only one', data)
    })
})

If you explicitly close the tmp database (using tmpDb.close()) the contents will be removed. If you restart your application previous tmp data will be overriden as well.

API

tmp = temp(db, [options])

Create a new temporary sublevel generator. Options are used as default for any tmp databases created afterwards. Optionally you can set prefix to a string that will prefix all tmp sublevels created.

var tmp = temp(db, {valueEncoding: 'json'}) // set valueEncoding: json all tmp sublevels

var tmpDb = tmp([options])

Create a new temporary sublevel.

Any options passed here are forwarded to levelup with the default values from the temp constructor mixed in.

Per default an increasing number is used to prefix the temporary sublevels. To change this set the prefix to whatever string you want to use as a prefix.

The returned tmpDb is a regular levelup that will have its contents garbage collected when you call tmpDb.close() or at some point in the future when the temporary sublevel prefix is being reused.

Author: Mafintosh
Source Code: https://github.com/mafintosh/level-temp 
License: MIT license

#javascript #temp #empty 

Level-temp: Create A Temporary Sublevel That Is Guaranteed to Be Empty

12素晴らしいLinuxコマンドとユーティリティ

Linux用のあまり知られていないユーティリティとコマンドの別のリストが戻ってきました。これはあなたが日常の仕事をより速く進めるのに役立ちます。

1.グーグル

私たちは、ブラウザのグラフィカルインターフェイスを介してGoogle検索を使用することに慣れています。ただし、これは、グラフィカルインターフェイスが使用できない環境では問題になります。googlerユーティリティを使用すると、コマンドラインからGoogle検索を実行できるようになります。

Googlerは、Linuxターミナル内でGoogle(Web&News&Search)にアクセスするためのフル機能のPythonベースのコマンドラインツールです。

URL:https ://github.com/jarun/googler

インストール方法:

# ubuntu$ sudo add-apt-repository ppa:twodopeshaggy/jarun
$ sudo apt-get update
$ sudo apt install googlerOR$ sudo snap install googler

使用例:

$ googler ford usa

グーグル実行中

2. sl(蒸気機関車)

コマンド「ls」を入力する代わりに、「sl」と入力した頻度はどれくらいですか。

面倒な「コマンドが見つかりません」というメッセージを表示する代わりに、この小さなユーティリティは素敵な画像を表示します。少なくともこのように、あなたは少し笑うか、次回はもっと注意するでしょう。

インストール方法:

$sudo apt install sl

使用例:

$ sl

slランニング

確かに、注意を引くのにも役立ちますが、最終的には面倒になる可能性があります。

3. hstr

hstrは私が毎日使用している優れたツールで、シェル履歴の提案ボックスに入力されたコマンドの履歴を簡単に表示、参照、検索できます。bashとzshで使用できます。

URL:http ://dvorka.github.io/hstr/

URL:https ://github.com/dvorka/hstr

インストール方法:

#Ubuntu
$ sudo add-apt-repository ppa:ultradvorka/ppa && sudo apt-get update && sudo apt-get install hstr && hstr --show-configuration >> ~/.bashrc && . ~/.bashrc

4.はい

Linuxにデフォルトで付属しているこのコマンドは、事前定義された応答を端末に渡すために使用できるシステム管理者にとって便利です。

使用例:

$ yes hello-world

はい実行中

5. rev(リバース)

与えられたすべての文字列を逆にします。これは時々役に立ちます。

使用例:

$ rev
$ hello world!

revrunning

良いことは、何もインストールする必要がないことです。

6. Wikit

このLinuxユーティリティは、コマンドラインからウィキペディアの記事を検索するために使用されます。

使用する必要があるのは、情報を取得する検索語を使用してコマンドを実行することだけです。

URL:https ://www.tecmint.com/wikipedia-commandline-tool/

インストール方法:

# Debian/Ubuntu$ sudo apt install nodejs	$ sudo npm install wikit -g

使用例:

Wikit matrix

ウィキの実行

7. pydf

このツールは、「df」コマンドの優れた代替手段です。Linuxファイルシステムで使用されているディスク容量と使用可能なディスク容量がdfコマンドと同じように表示されますが、色が異なり、結果をカスタマイズすることもできます。

Pythonで書かれていることに注意してください。

URL:https ://pypi.org/project/pydf/

#Ubuntu# only if you do not have phyton installed:
$ sudo apt install python3-pip
$ pip install pydf

実行中のpydf

8.trash-cli

Trash-cliは、ファイルをゴミ箱に移動し、元の絶対パス、削除日、およびアクセス許可を記録するコマンドラインインターフェイスです。

URL:https://github.com/andreafrancia/trash-cli

インストール方法:

# Debian/Ubuntu systems
$ sudo easy_install trash-cli

使用例:

# We create an example file named file1
$ echo "hello world!" > file1
$ trash-put file1
#
$ trash-list

使用可能なコマンド:

$ trash-put           #trash files and directories.
$ trash-list          #list trashed files.
$ trash-restore       #restore a trashed file.
$ trash-rm            #remove individual files from the trashcan.
$ trash-empty         #empty the trashcan(s).

trash-cliの実行

9. eSpeak NG

eSpeak NGは、英語やその他の言語でテキストを音声に変換するために使用できる無料のオープンソースソフトウェアです。これは、JonathanDuddingtonによって作成されたeSpeakエンジンに基づいています。

URL: https://github.com/espeak-ng/espeak-ng

インストール方法:

# Ubuntu
$ apt-get install espeak

それでは、「こんにちはケスク!」というセリフを話しましょう。そしてそれをhello.mp4オーディオファイルに録音します:

$ espeak "Hi Kesk!" -w hello.mp4 -g 60 -p 70 -s 100 -v en-us

録音したいテキストファイルを指定することもできます。

$ espeak -f example.txt -w example.mp4 -g 60 -p 70 -s 100 -v en-us

今、あなたがしなければならないのはあなたの好きなアプリケーションでそれをプレイすることだけです、そしてそれはそれです。

10.一瞥

このコマンドラインシステム監視ユーティリティを使用すると、CPU、負荷平均、メモリ、ネットワークインターフェイス、ディスクI / O、プロセス、およびファイルシステムスペースの使用率を監視できます。

GlancesユーティリティはPythonで記述されており、psutilライブラリを使用してシステム情報を取得し、わかりやすい形式で表示します。

また、構成ファイルを使用してさまざまな警告しきい値を設定することもできます。

すべてを管理するのに非常に便利です。

URL:https ://nicolargo.github.io/glances/

インストール方法:

$ sudo apt install glances

使用例:

$ glances

走っている一瞥

11.gtop

gtopユーティリティは、システムとそのプロセスに関するさまざまな情報を表示するLinuxシステムモニターです。

このツールは使いやすく、リソースをほとんど消費しないため、リソースを無駄にすることなく実行できます。さらに、オペレーティングシステムのコマンドを使用するため、非常に印象的で正確な方法で情報を表示します。

これは、CanGüneyAksakalliによってJavaScriptで開発されたオープンソースツールであり、インストールして実行するには、コンピューターにnodejsをインストールする必要があります。

URL:git clone https://github.com/aksakalli/gtop.git

インストール方法:

$ sudo npm install gtop -g

使用例:

$ gtop

gtopランニング

12.ファクター

以前のユーティリティと同様に、この小さなプログラムはデフォルトであり、ある時点で役立つ場合があります。

ファクターランニング

Linuxのコマンドラインユーティリティや、特に役立つコマンドやあまり知られていないコマンドをご存知の場合は、それについて教えていただければ幸いです。

ありがとうございました!

ソース:https ://medium.com/codex/12-awesome-linux-commands-utilities-49ab56588a84

#linux 

12素晴らしいLinuxコマンドとユーティリティ

12 Increíbles Comandos Y Utilidades De Linux

Vuelvo con otra lista de utilidades y comandos poco conocidos para Linux que te ayudarán a ir más rápido con tu trabajo diario.

1. googleador

Estamos acostumbrados a utilizar la búsqueda de Google a través de una interfaz gráfica en el navegador. Sin embargo, esto es un problema en entornos donde la interfaz gráfica no está disponible. Con la utilidad googler podremos realizar búsquedas en Google desde la línea de comandos.

Googler es una herramienta de línea de comandos basada en Python con todas las funciones para acceder a Google (Web & News & Search) dentro de la terminal de Linux.

URL: https://github.com/jarun/googler

Cómo instalarlo:

# ubuntu$ sudo add-apt-repository ppa:twodopeshaggy/jarun
$ sudo apt-get update
$ sudo apt install googlerOR$ sudo snap install googler

Ejemplo de uso:

$ googler ford usa

google corriendo

2. sl (Locomotora de vapor)

En lugar de escribir el comando 'ls', ¿con qué frecuencia ha escrito 'sl'?

En lugar de mostrarte el tedioso mensaje de "comando no encontrado", esta pequeña utilidad te mostrará una bonita imagen; al menos así te reirás un poco o tendrás más cuidado la próxima vez.

Cómo instalarlo:

$sudo apt install sl

Ejemplo de uso:

$ sl

sl corriendo

Es cierto que al final puede resultar cansino, aunque también servirá para que prestes atención.

3. calle

hstr es una gran herramienta que uso a diario que le permite ver, explorar y buscar fácilmente el historial de comandos ingresados ​​en el cuadro de sugerencias del historial de shell. Está disponible para bash y zsh.

URL: http://dvorka.github.io/hstr/

URL: https://github.com/dvorka/hstr

Cómo instalarlo:

#Ubuntu
$ sudo add-apt-repository ppa:ultradvorka/ppa && sudo apt-get update && sudo apt-get install hstr && hstr --show-configuration >> ~/.bashrc && . ~/.bashrc

4. si

Este comando que viene por defecto en Linux es útil para los administradores de sistemas que pueden usarlo para pasar una respuesta predefinida a la terminal.

Ejemplo de uso:

$ yes hello-world

si corriendo

5. rev (Reversa)

Invierte cada cadena que se le da, lo que a veces es útil.

Ejemplo de uso:

$ rev
$ hello world!

revoluciones corriendo

Lo bueno es que no tienes que instalar nada.

6. Wiki

Esta utilidad de Linux se utiliza para buscar artículos de Wikipedia desde la línea de comandos.

Lo único que tienes que hacer para usar es ejecutar el comando con el término de búsqueda que deseas obtener la información.

URL: https://www.tecmint.com/wikipedia-commandline-tool/

Cómo instalarlo:

# Debian/Ubuntu$ sudo apt install nodejs	$ sudo npm install wikit -g

Ejemplo de uso:

Wikit matrix

corriendo

7. pdf

Esta herramienta es una excelente alternativa al comando “df”. Muestra la cantidad de espacio en disco utilizado y disponible en un sistema de archivos de Linux, al igual que el comando df, pero con diferentes colores, y también le permite personalizar los resultados.

Tenga en cuenta que está escrito en Python.

URL: https://pypi.org/project/pydf/

#Ubuntu# only if you do not have phyton installed:
$ sudo apt install python3-pip
$ pip install pydf

pdf ejecutando

8. basura-cli

Trash-cli es una interfaz de línea de comandos que desecha archivos y registra la ruta absoluta original, la fecha de eliminación y los permisos.

URL: https://github.com/andreafrancia/trash-cli

Cómo instalarlo:

# Debian/Ubuntu systems
$ sudo easy_install trash-cli

Ejemplo de uso:

# We create an example file named file1
$ echo "hello world!" > file1
$ trash-put file1
#
$ trash-list

Comandos disponibles:

$ trash-put           #trash files and directories.
$ trash-list          #list trashed files.
$ trash-restore       #restore a trashed file.
$ trash-rm            #remove individual files from the trashcan.
$ trash-empty         #empty the trashcan(s).

basura-cli corriendo

9. eSpeak NG

eSpeak NG es un software gratuito y de código abierto que se puede utilizar para convertir texto a voz en inglés y otros idiomas. Se basa en el motor eSpeak creado por Jonathan Duddington.

URL: https://github.com/espeak-ng/espeak-ng

Cómo instalarlo:

# Ubuntu
$ apt-get install espeak

Ahora, digamos la línea "¡Hola, Kesk!" y grábelo en el archivo de audio hello.mp4:

$ espeak "Hi Kesk!" -w hello.mp4 -g 60 -p 70 -s 100 -v en-us

También puede especificar el archivo de texto que desea grabar.

$ espeak -f example.txt -w example.mp4 -g 60 -p 70 -s 100 -v en-us

Ahora todo lo que tienes que hacer es jugarlo con tu aplicación favorita, y listo.

10. miradas

Esta utilidad de monitoreo del sistema de línea de comandos le permite monitorear la CPU, el promedio de carga, la memoria, las interfaces de red, la E/S del disco, los procesos y la utilización del espacio del sistema de archivos.

La utilidad Glances está escrita en Python y utiliza la biblioteca psutil para obtener información del sistema y mostrarla en un formato amigable.

También nos permite establecer diferentes umbrales de alerta mediante un archivo de configuración.

Muy útil para tenerlo todo bajo control.

URL: https://nicolargo.github.io/glances/

Cómo instalarlo:

$ sudo apt install glances

Ejemplo de uso:

$ glances

miradas corriendo

11. arriba

La utilidad gtop es un monitor del sistema Linux que muestra diversa información sobre el sistema y sus procesos.

La herramienta es fácil de usar y consume muy pocos recursos, por lo que podemos tenerla funcionando sin gastar recursos. Además, muestra la información de una forma bastante llamativa y precisa ya que utiliza comandos del sistema operativo.

Es una herramienta de código abierto desarrollada en JavaScript por Can Güney Aksakalli, y necesitará tener instalado nodejs en su computadora para instalarlo y ejecutarlo.

URL: clon de git https://github.com/aksakalli/gtop.git

Cómo instalarlo:

$ sudo npm install gtop -g

Ejemplo de uso:

$ gtop

corriendo

12. factor

Al igual que la utilidad anterior, este pequeño programa viene por defecto y puede ser de ayuda en algún momento.

funcionamiento del factor

Si conoces alguna utilidad de línea de comandos de Linux o algún comando que te ayude especialmente y no sea muy conocido, te agradecería que nos lo comentaras.

¡Gracias!

Fuente: https://medium.com/codex/12-awesome-linux-commands-utilities-49ab56588a84

#linux 

12 Increíbles Comandos Y Utilidades De Linux

How To Check Array Is Empty Or Null In Javascript

In this example i will show you how to check array is empty or null in JavaScript or jQuery. When we are working in java script and you want to loop the array that time we need to check whether array is empty or not, so it doesn’t return error.

There are many ways to check Java script array is empty or not so I will give you some examples.

How To Check Array Is Empty Or Null In JavaScript

https://websolutionstuff.com/post/how-to-check-array-is-empty-or-null-in-javascript

Thanks for the reading…!!

#javascript #jquery #php #array #empty #null

How To Check Array Is Empty Or Null In Javascript
Enos  Prosacco

Enos Prosacco

1590570452

How To Empty An Array In JavaScript

In this tutorial, we will learn how to Empty an Array in JavaScript. You can simply use the array's length property to empty an array in JavaScript.

Example

var arr1 = [1,2,3,4,5];

// Reference arr1 by another variable
var arr2 = arr1;

// Making arr1 empty
arr1.length = 0;

console.log(arr1.length); // Prints: 0
console.log(arr2.length); // Prints: 0

You can alternatively use the square bracket notation to empty an array, such as arr1 = [], if you don't have any references to the original array arr1 anywhere else in your code, because it creates a brand new empty array instead of emptying the original array, as you can see here:

Example

var arr1 = [1,2,3,4,5];

// Reference arr1 by another variable
var arr2 = arr1;

// Making arr1 empty
arr1 = [];

console.log(arr1.length); // Prints: 0
console.log(arr2.length); // Prints: 5

#javascript #clear array #empty array #java