aguarde...

14 de setembro de 2020

Primeiros passos com a API JavaScript Fetch

Primeiros passos com a API JavaScript Fetch

No passado, havia duas maneiras de fazer solicitações. Um estava com XMLHttpRequest. A outra foi com jQuery, ou seja, o ajax()método. Felizmente, o JavaScript agora oferece uma terceira forma, a API Fetch. Neste tutorial, você aprenderá tudo o que precisa saber para começar a usar a API JavaScript Fetch.

Uma introdução rápida

A API Fetch é uma adição mais recente ao padrão JavaScript. O que esta API faz é fornecer uma maneira mais fácil e limpa de fazer solicitações ao servidor. O que é ainda melhor é que essa API é baseada em promessas . Isso o torna mais fácil e amigável de usar. É também o que o torna preferível a ambos XMLHttpRequeste também ao jQuery ajax().

Os princípios básicos da API JavaScript Fetch

Quando você deseja fazer solicitações com fetch API, você precisará principalmente de duas coisas. O primeiro é o fetch()método. Esse método é o que faz a solicitação. Este método requer um argumento, o caminho ou URL ao qual você deseja fazer a solicitação. Além desse argumento, você também pode fornecer esse método com o objeto config.

Este objeto de configuração é opcional. Ele permite que você defina várias configurações para a solicitação. Por exemplo, você pode adicionar cabeçalhos, corpo com alguns dados, definir modo para solicitações de origem cruzada, habilitar cache, permitir ou desautorizar redirecionamento, especificar referenciadores e referrerPolicy e assim por diante. Você pode encontrar todas as opções disponíveis no MDN .

// Fetch syntax
fetch(someURL, {})

// or with optional config object
fetch(someURL, {/* settings go here */})

Lidando com fetch com funções de manipulador de promessa

A segunda coisa de que você precisa são funções de tratamento de promessa . Como discutimos brevemente, a API fetch é baseada em promessas. Isso significa que toda vez que você fizer uma solicitação o resultado, os dados retornados pelo fetch()método, serão uma promessa. Para processar essa promessa, você precisará usar uma das funções de manipulador de promessa.

Duas funções de manipulador que você provavelmente usará com mais freqüência são then()catch(). A then()função de manipulador ajuda você a lidar com o estado de cumprimento de uma promessa. Isso se aplica a promessas resolvidas e rejeitadas. Outra maneira de lidar com promessas rejeitadas é usando o catch().

Ambos, then()catch()podem lidar com promessas rejeitadas. No entanto, apenas o then()pode lidar com promessas resolvidas. Portanto, certifique-se de usar then()pelo menos para lidar com o estado resolvido de uma promessa. Para lidar com o estado rejeitado, decida se deseja usar then()catch().

Quando a promessa de busca é cumprida, os dados recebidos são automaticamente passados ​​para funções de tratamento anexadas a ele. Quando você deseja trabalhar com esses dados, precisa fazer isso de dentro dessas funções de manipulador. Se quiser disponibilizar esses dados fora deles, você pode atribuir os dados a alguma variável externa.

// Use fetch() method with promise handler functions
fetch(someUrl)
  .then(response => {
    // When promise gets resolved
    // log received data to console
    console.log(response)
  })
  .catch(error => {
    // If promise gets rejected
    // log the error to console
    console.log(error)
  })


// Real-world example
fetch('https://sv443.net/jokeapi/v2/joke/Programming')
  // Convert response to JSON format
  .then(response => response.json())
  // Log the response JSON
  .then(jsonData => console.log(jsonData))
  .catch(error => {
    // If promise gets rejected
    // log the error to console
    console.log(error)
  })

// Output:
// {
//   error: false,
//   category: 'Programming',
//   type: 'twopart',
//   setup: 'Programming is like sex.',
//   delivery: 'Make one mistake and you end up supporting it for the rest of your life.',
//   flags: {
//     nsfw: true,
//     religious: false,
//     political: false,
//     racist: false,
//     sexist: false
//   },
//   id: 8,
//   lang: 'en'
// }

Como você pode ver no exemplo acima, você pode encadear as funções do manipulador de promessa uma após a outra. É uma boa prática colocar a then()(s) função (ões) como primeira e catch()como segunda. Se você também usar finally(), é uma boa prática colocar esse como o último.

Lidar com buscar com esperar

Outra opção, se você não quiser usar funções de manipulador de promessa, é await . O awaitfaz duas coisas. Primeiro, ele pausa a execução do código circundante até que uma promessa que segue essa palavra-chave seja cumprida. A segunda coisa que awaitfaz é substituir a then()função. Ele extrai e atribui automaticamente os dados retornados por uma promessa a uma variável.

Há duas coisas que você deve lembrar se quiser usar await. Primeiro, use-o dentro da instrução try … catch . O await complementa a then()função. No entanto, ele não complementa o catch(). Se quiser detectar qualquer erro que possa surgir, você pode pegar com a try...catchinstrução.

A segunda coisa é que, até o nível superior await ser lançado, você pode usar awaitapenas em funções assíncronas . Isso é o que você pode fazer. Use fetch()junto com await. Em seguida, envolva esses dois com try...catchinstrução e coloque tudo dentro da asyncfunção.

// Create async function
async function makeRequest() {
  // Use try...catch statement
  try {
    // Use await and make fetch request
    const responseData = await fetch('https://sv443.net/jokeapi/v2/joke/Any')
    // Convert the response to JSON format
    const responseJSON = await responseData.json()

    // Log the converted JSON
    console.log(responseJSON)
  }
  catch (error) {
    // Log any error
    console.log(error)
  }
}

// Call the makeRequest()
makeRequest()
// Output:
// {
//   error: false,
//   category: 'Miscellaneous',
//   type: 'twopart',
//   setup: "Mom asked me where I'm taking her to go out to eat for mother's day.",
//   delivery: 'I told her, "We already have food in the house".',
//   flags: {
//     nsfw: false,
//     religious: false,
//     political: false,
//     racist: false,
//     sexist: false
//   },
//   id: 89,
//   lang: 'en'
// }

Processando a resposta

Quando você faz uma solicitação, a promessa retornada por fetch()retorna um objeto de resposta. Este objeto contém informações recebidas do servidor e também vários métodos. Podemos usar esses métodos para trabalhar com os dados. Estes métodos são clone()redirect()arrayBuffer()formData()blob()text()json().

clone()método cria um clone da resposta. O redirect()método cria uma nova resposta, mas com um URL diferente. O arrayBuffer()retorna a resposta como ArrayBuffer . O formData()retorna a resposta como objeto FormData . O blob()retorno retorna a resposta como um Blob.

text()retorna a resposta como uma string ou texto. O último, o json(), retorna a resposta como JSON. Qual desses métodos você deve usar para analisar a resposta depende do tipo de dados que você espera. Por exemplo, se você espera receber dados na forma de um JSON, use json(), se texto, use text()e assim por diante.

O bom sobre esse método é que você não precisa necessariamente saber que resposta deve esperar. Esses métodos que analisam a resposta, como text()json()geralmente funcionam mesmo se você escolher o método errado para o trabalho. Por exemplo, digamos que você use o text()método, mas a resposta será um JSON.

Nesse caso, o text()método será capaz de escolher esse JSON e analisá-lo como uma string. O resultado será basicamente JSON stringificado. Dito isso, o mesmo não funcionará com resposta de texto e json(). O json()espera uma sintaxe específica. Se a resposta for um texto simples e você usar json(), obterá um erro de sintaxe.

Portanto, se você não tiver certeza de que tipo de resposta deve esperar, use text(). Na pior das hipóteses, você obterá algum JSON stringificado e saberá que deve usar em seu json()lugar. Se você espera outro formato, use o método correspondente: response.formData()response.blob()ou response.arrayBuffer().

// Example no.1:
// Parsing response as a text
async function makeRequest() {
  // Use try...catch statement
  try {
    // Make fetch request
    const responseData = await fetch('https://sv443.net/jokeapi/v2/joke/Programming')

    // Parsing as Text happens here:
    // Parse the response as a text
    const responseText = await responseData.text()

    // Log the text
    console.log(responseText)
  }
  catch (error) {
    // Log any error
    console.log(error)
  }
}

// Call the makeRequest()
makeRequest()
// Output:
// '{
//   error: false,
//   category: 'Programming',
//   type: 'single',
//   joke: 'Programming is 10% science, 20% ingenuity, and 70% getting the ingenuity to work with the science.',
//   flags: {
//     nsfw: false,
//     religious: false,
//     political: false,
//     racist: false,
//     sexist: false
//   },
//   id: 37,
//   lang: 'en'
// }'


// Alternative:
fetch('https://sv443.net/jokeapi/v2/joke/Programming')
  .then(response => response.text())
  .then(responseText => console.log(responseText))
  .catch(err => console.log(err))


// Example no.2:
// Parsing response as a text
async function makeRequest() {
  // Use try...catch statement
  try {
    // Make fetch request
    const responseData = await fetch('https://sv443.net/jokeapi/v2/joke/Programming')

    // Parsing as JSON happens here:
    // Parse the response as a JSON
    const responseJSON = await responseData.json()

    // Log the JSON
    console.log(responseJSON)
  }
  catch (error) {
    // Log any error
    console.log(error)
  }
}

// Call the makeRequest()
makeRequest()
// Output:
// {
//   error: false,
//   category: 'Programming',
//   type: 'twopart',
//   setup: 'How do you generate a random string?',
//   delivery: 'Put a Windows user in front of Vim and tell him to exit.',
//   flags: {
//     nsfw: false,
//     religious: false,
//     political: false,
//     racist: false,
//     sexist: false
//   },
//   id: 129,
//   lang: 'en'
// }


// Alternative:
fetch('https://sv443.net/jokeapi/v2/joke/Programming')
  .then(response => response.json())
  .then(responseJSON => console.log(responseJSON))
  .catch(err => console.log(err))

Processando resposta já processada

Quando você processa a resposta com um método, para analisá-la em um formato, você não pode processá-la novamente e analisá-la em outro formato. Se você analisar a resposta como um texto, não poderá pegar a resposta e analisá-la novamente como JSON. Depois de analisar a resposta, ela será bloqueada. Analisá-lo novamente levará a TypeError.

async function makeRequest() {
  // Use try...catch statement
  try {
    // Make fetch request
    const responseData = await fetch('https://sv443.net/jokeapi/v2/joke/Programming')

    // Parse the response as a text
    const responseText = await responseData.text()

    // This will not work after the first parsing
    // Try to parse the response again as a JSON
    const responseJSON = await responseData.json()

    // Log the text
    console.log(responseText)

    // Log the JSON
    console.log(responseJSON)
  }
  catch (error) {
    // Log any error
    console.log(error)
  }
}

// Call the makeRequest()
makeRequest()
// Output:
// TypeError: Failed to execute 'json' on 'Response': body stream is locked

Fazendo solicitação com fetch

O tipo padrão de solicitação que o fetch()método faz é GET. Se você quiser fazer um tipo diferente de solicitação, poderá alterá-lo. Você pode alterar o tipo de solicitação por meio do objeto de configuração opcional que pode ser passado como o segundo argumento para o fetch()método. Por exemplo, você pode definir methodcomo POSTpara fazer uma POSTsolicitação e assim por diante.

O pedido GET

Se você usar o fetch()método como está e fornecê-lo apenas com o URL, ele executará a GETsolicitação automaticamente .

// GET request example
async function makeGetRequest() {
  // Use try...catch statement
  try {
    // Make GET fetch request
    const responseData = await fetch('https://sv443.net/jokeapi/v2/joke/Programming')

    // Parse the response as a JSON
    const responseJSON = await responseData.json()

    // Log the JSON
    console.log(responseJSON)
  }
  catch (error) {
    // Log any error
    console.log(error)
  }
}

// Call the makeGetRequest()
makeGetRequest()
// Output:
// {
//   error: false,
//   category: 'Programming',
//   type: 'single',
//   joke: "Knock knock.
// Who's there?
// Recursion.
// Recursion who?
// Knock knock.",
//   flags: {
//     nsfw: false,
//     religious: false,
//     political: false,
//     racist: false,
//     sexist: false
//   },
//   id: 182,
//   lang: 'en'
// }


// Alternative with promise handler functions:
fetch('https://sv443.net/jokeapi/v2/joke/Programming')
  .then(response => response.json())
  .then(responseJSON => console.log(responseJSON))
  .catch(err => console.log(err))

O pedido POST

Outro tipo popular de solicitação é POST. Você pode fazer esse tipo de solicitação com fetch API se alterar o methodobjeto de configuração on. Este objeto é o segundo argumento opcional para o qual você pode passar fetch(). Se você definir o methodpara, POSTfetch()método executará uma POSTsolicitação.

Ao fazer uma POSTsolicitação, você precisará enviar alguns dados. Você pode adicionar esses dados por meio da bodyopção. Esta opção também está no objeto de configuração. Além disso, você também pode querer alterar o Content-Type. Você pode fazer isso via headersopção. No entanto, para um simples, POSTapenas o methodbodypode ser o suficiente.

// Some data to send
const userData = {
  firstName: 'Tom',
  lastName: 'Jones',
  email: 'tom@jones.ai'
}

// Make POST request
async function makePostRequest() {
  // Use try...catch statement
  try {
    // Make fetch request
    const responseData = await fetch('/users/register', {
      method: 'POST', // Change the request method
      headers: { // Change the Content-Type
        'Content-Type': 'application/json;charset=utf-8'
      },
      body: JSON.stringify(userData) // Add data you want to send
    })

    // Parse the response as a JSON
    const responseJSON = await responseData.json()

    // Log the JSON
    console.log(responseJSON)
  }
  catch (error) {
    // Log any error
    console.log(error)
  }
}

// Call the makePostRequest()
makePostRequest()


// Alternative with promise handler functions:
fetch('/users/register', {
  method: 'POST', // Change the request method
  headers: { // Change the Content-Type
    'Content-Type': 'application/json;charset=utf-8'
  },
  body: JSON.stringify(userData) // Add data you want to send
})
  .then(response => response.json())
  .then(responseJSON => console.log(responseJSON))
  .catch(err => console.log(err))

O pedido DELETE

Quando você quiser excluir alguns dados, arquivos, etc., você pode fazer um DELETEpedido. Fazer esse tipo de solicitação requer um pouco mais de sintaxe, GETmas menos POST. O que você precisa fazer é definir a methodopção para fetch()DELETE. Em seguida, você precisa saber o URL correto e o que deseja excluir.

// Make DELETE request
async function makeDeleteRequest() {
  // Use try...catch statement
  try {
    // Make fetch request
    const responseData = await fetch('/users/tom', {
      method: 'DELETE' // Change the request method
    })

    // Parse the response as a JSON
    const responseJSON = await responseData.json()

    // Log the JSON
    console.log(responseJSON)
  }
  catch (error) {
    // Log any error
    console.log(error)
  }
}

// Call the makeRequest()
makeDeleteRequest()


// Alternative with promise handler functions:
fetch('/users/tom', {
  method: 'DELETE', // Change the request method
})
  .then(response => response.text())
  .then(responseText => console.log(responseText))
  .catch(err => console.log(err))

O pedido PUT

PUTtipo de solicitação é mais frequentemente usado para atualizar dados ou recursos existentes. Esta solicitação é quase igual a POST. A principal, e às vezes única, diferença é que a methodopção para fetch()deve ser definida como PUT.

// Some data to send to update existing records
const userData = {
  firstName: 'Jack',
  lastName: 'O\'Brian',
  email: 'jack@obrian.co'
}

// Make Put request
async function makePutRequest() {
  // Use try...catch statement
  try {
    // Make fetch request
    const responseData = await fetch('/users/jack', {
      method: 'PUT', // Change the request method
      body: JSON.stringify(userData) // Add data you want to send
    })

    // Parse the response as a JSON
    const responseJSON = await responseData.json()

    // Log the JSON
    console.log(responseJSON)
  }
  catch (error) {
    // Log any error
    console.log(error)
  }
}

// Call the makePutRequest()
makePutRequest()


// Alternative with promise handler functions:
fetch('/users/jack', {
  method: 'PUT', // Change the request method
  body: JSON.stringify(userData) // Add data you want to send
})
  .then(response => response.json())
  .then(responseJSON => console.log(responseJSON))
  .catch(err => console.log(err))

O pedido PATCH

Este PATCHé o último tipo de solicitação que você pode fazer com fetch API que discutiremos. Esse tipo de solicitação é muito semelhante ao PUT. A diferença entre os dois é que PUTé usado para atualizar a versão antiga com a nova versão. Ou seja, você atualiza tudo. Com PATCH, você atualiza apenas parte dos dados existentes, e-mail do usuário, por exemplo.

// Some data to send to update
// only a part of existing records
const userData = {
  email: 'jack@obrian.co'
}

// Make PATCH request
async function makePatchRequest() {
  // Use try...catch statement
  try {
    // Make fetch request
    const responseData = await fetch('/users/jack', {
      method: 'PATCH', // Change the request method
      body: JSON.stringify(userData) // Add data you want to send
    })

    // Parse the response as a JSON
    const responseJSON = await responseData.json()

    // Log the JSON
    console.log(responseJSON)
  }
  catch (error) {
    // Log any error
    console.log(error)
  }
}

// Call the makePatchRequest()
makePatchRequest()


// Alternative with promise handler functions:
fetch('/users/jack', {
  method: 'PATCH', // Change the request method
  body: JSON.stringify(userData) // Add data you want to send
})
  .then(response => response.json())
  .then(responseJSON => console.log(responseJSON))
  .catch(err => console.log(err))

Uma observação sobre o objeto Response

Discutimos brevemente os métodos que você pode usar no objeto Response. A text()json()formData()blob()arrayBuffer()clone()redirect(). Esses métodos não são tudo o que o objeto Response contém. Ele também contém várias propriedades. É possível que algumas dessas propriedades sejam úteis.

Algumas das propriedades mais úteis são statusTextstatusok. O statusTexté uma string que contém a mensagem do código de status HTTP. O statusé um número que especifica o código de status da resposta. Quando você faz uma solicitação e ela é bem-sucedida, ela terá o statusvalor de 200.

oké um booleano que especifica se statusestá no intervalo de códigos de 200 a 299. Portanto, se sua solicitação for bem-sucedida, 200, o valor de okserá true. Uma Coisa. Também há bodypropriedade. Esta propriedade contém os dados que você recebeu. Quando você usa algum método para analisar a resposta, ele funciona com essa bodypropriedade.

// Make fetch request
fetch('https://sv443.net/jokeapi/v2/joke/Programming')
  .then(response => console.log(response)) // Log the Response object
  .catch(err => console.log(err))

// Output:
// {
//   body: (...)
//   bodyUsed: false
//   headers: Headers
//   ok: true
//   redirected: false
//   status: 200
//   statusText: ""
//   type: "cors"
//   url: "https://sv443.net/jokeapi/v2/joke/Programming"
// }

Conclusão: Primeiros passos com a API JavaScript Fetch

A API JavaScript Fetch fornece uma maneira fácil e amigável de fazer solicitações. Espero que este tutorial ajude você a aprender sobre o que é fetch API e como funciona. Também espero que os exemplos com os quais trabalhamos ajudaram você a entender como usar essa API. Como fazer solicitações bem-sucedidas e como trabalhar com as respostas da maneira certa.

Posted in Blog
Write a comment