Executando verificação de segurança...
49

Use URL Constructor ao invés de template literals para escrever suas URLs

Fala pessoal, hoje eu vim trazer uma dica rápida para vocês que ajudou a tornar meu código mais semântico.

Muitas vezes, trabalhando com backend ou frontend, precisamos fazer algumas requisições com alguns parâmetros, certo?

E eu costumava escrever a URL das minhas requisições dessas forma:

const url = `http://localhost:3000/endpoint?param1=${var1}&param2=${var2}&param3=${var3}`

Convenhamos que essa URL é difícil de ler e até de dar manutenção, sempre precisamos identificar o que é parâmetro, o que é variável e o que é apenas a sintaxe do código Javascript.

Para resolver esse problema de semântica, descobri o URL Constructor, que realiza a mesma função que o código acima, porém de uma forma mais eficiente e elegante.

Então, podemos reescrever o mesmo código desta forma:

const url = new URL('http://localhost:3000/endpoint')

url.searchParams.set('param1', var1)
url.searchParams.set('param2', var2)
url.searchParams.set('param3', var3)

O código fala por si só. Na primeira linha, criamos a URL base do endpoint e nas linhas seguintes adicionamos os search params necessários.

Pronto, agora a variável url contém os mesmos search params que antes, mas agora utilizando a classe URL, deixando o código mais simples e muito mais fácil de manter.

E você, já tinha utilizado a classe URL alguma vez? Quem sabe para alguma outra finalidade? Me conta aí.

Carregando publicação patrocinada...
19

Muito bom!

Este é um recurso que - minha impressão - poucas pessoas usam no dia-a-dia (infelizmente).

Outro ponto muito importante é que o searchParams já cuida de vários detalhes chatos pra vc. Por exemplo, se o valor do parâmetro tiver caracteres como & ou =, ele já trata corretamente:

const url = new URL('http://localhost:3000/endpoint');
url.searchParams.set('param1', 'a&b=c');

console.log(url.toString()); // http://localhost:3000/endpoint?param1=a%26b%3Dc

Repare que ao converter a URL para string, já é feito automaticamente o URL encoding dos caracteres & e = para %26 e %3D. Assim o valor é enviado corretamente (no caso, o parâmetro param1 com o valor a&b=c).

Se eu fizesse a concatenação de strings, a URL ficaria http://localhost:3000/endpoint?param1=a&b=c, ou seja, seriam enviados dois parâmetros (param1 com o valor a e b com o valor c). Para ficar correto, vc teria que fazer a substituição manualmente, mas pra que fazer isso se o searchParams já cuida disso pra vc?


Outro caso interessante que ele já trata é quando a URL tem anchor, pois este sempre deve ficar no final.

const url = new URL('http://localhost:3000/endpoint#anchor');
url.searchParams.set('param1', 'a');

console.log(url.toString()); // http://localhost:3000/endpoint?param1=a#anchor

console.log(url.searchParams); // URLSearchParams { 'param1' => 'a' }
console.log(url.hash); // #anchor

Ou seja, se vc sempre adicionar os parâmetros no final, ficaria http://localhost:3000/endpoint#anchor?param1=a. Mas está errado, pois neste caso, ela fica sem nenhum parâmetro, e o anchor é tudo que vem depois do #, veja:

// ERRADO: adicionar o parâmetro depois do anchor
const url = new URL('http://localhost:3000/endpoint#anchor?param1=a');

console.log(url.searchParams); // URLSearchParams {} (vazio)
console.log(url.hash); // #anchor?param1=a

Além disso, o searchParams permite fácil acesso aos parâmetros:

const url = new URL('http://localhost:3000/endpoint?param1=a&param2=b&param3=c');

// obter um parâmetro específico
console.log(url.searchParams.get('param1')); // a

// loop por todos
for (const [nome, valor] of url.searchParams) {
    console.log(`${nome} = ${valor}`);
}

Se pesquisar por aí, vc até vai encontrar "soluções" que envolvem regex ou concatenação de strings. E pode até "funcionar", até o momento em que vc se depara com estes casos especiais. O mais correto e garantido é usar o searchParams, que já cuida de todos esses casos.


Outra vantagem de se usar o objeto URL é que dá para separar facilmente os componentes da URL:

const url = new URL('http://user:senha@localhost:3000/endpoint/v1?param1=a&param2=b#anchor');

console.log(url.protocol); // http:
console.log(url.username); // user
console.log(url.password); // senha
console.log(url.host); // localhost:3000
console.log(url.hostname); // localhost
console.log(url.port); // 3000
console.log(url.pathname); // /endpoint/v1
console.log(url.search); // ?param1=a&param2=b
console.log(url.hash); // #anchor

Até daria pra fazer uma regex (a "solução" mais comum se vc pesquisar), mas é algo bem propenso a erros, e se torna tão complexo para tratar casos especiais que acaba não valendo a pena.

Por fim, outra vantagem é que o construtor dá erro caso a URL seja inválida (por exemplo, new URL('abc') lança um TypeError), ou seja, vc também já garante a validação - o que é mais trabalhoso se for verificar a string manualmente.


Para mais detalhes, consulte a documentação:

3

Já trabalhei em lugares que preferiram regex ao url, eu ja bati tanta boca por causa disso kkkk, sendo que é muito prático, semantico e simples, um ótimo conhecimento pra quem ainda não sabe ou não precisou implementar algo com urls no JS, uma mão na roda sem dúvidas

1

Eu faço da primeira forma. Não sei dizer muito bem o motivo, mas me parece mais natural, mais fluido do que a segunda opção. Mas foi bem útil a informação.