Novedades ES6

Novedades en ES6 - API fetch

La API Fetch proporciona una interfaz para recuperar recursos (incluso a través de la red). Resultará familiar a cualquiera que haya usado XMLHttpRequest, pero la nueva API ofrece un conjunto de características más potente y flexible.

Conceptos y uso

Fetch ofrece una definición genérica de los objetos Request y Response (y otras cosas relacionadas con las solicitudes de red). Esto permitirá su uso donde sea necesario en un futuro, ya sea para operadores de servicios, API caché y otras cosas similares que manipulen o modifiquen las solicitudes y respuestas, o cualquier otro tipo de caso de uso que pudiera requerirle la generación de sus propias respuestas mediante programación.

También proporciona una definición para conceptos relacionados, como CORS y la semántica de encabezado HTTP origen, suplantando sus definiciones separadas en otros lugares.

Para hacer una solicitud y recuperar un recurso, utilice el método GlobalFetch.fetch. Se implementa en múltiples interfaces, específicamente Window y WorkerGlobalScope. Esto hace que esté disponible en casi cualquier contexto donde quiera buscar recursos.

El método fetch() toma un argumento obligatorio, la ruta de acceso al recurso que desea recuperar. Devuelve una Promise que resuelve en Response a esa petición, sea o no correcta. También puede pasar opcionalmente un objeto de opciones init como segundo argumento (ver Request).

Una vez que Response es recuperada, hay varios métodos disponibles para definir cuál es el contenido del cuerpo y como se debe manejar (ver Body).

Puede crear una solicitud y respuesta directamente a con los constructores Request() y Response(), pero no es recomendable hacerlo directamente. En su lugar, es preferible que sean creados como resultado de otras acciones de la API (por ejemplo, FetchEvent.respondWith desde los operadores de servicios).

Recuperar archivo json con la API fetch

El API fech remplaza las peticiones asíncronas del objeto XMLHttpRequest que hemos utilizado y seguimos utilizando en sitos web que tienen algunos años, es más conocida esta tecnología con el término Ajax .

El API fetch proporciona una mecánica más organizada para hacer peticiones asíncronas a servidores web.

El API fetch se base en un método llamado 'fetch' que depende del objeto 'window' como sucede con otros métodos vistos como 'alert', 'prompt' etc.

La sintáxis es muy sencilla, si tenemos que solicitar un archivo con formato JSON a un servidor web tenemos:

<!DOCTYPE html>
<html>

<head>
  <title>Ejemplo de JavaScript</title>
  <meta charset="UTF-8">
</head>

<body>
  </div>
  <script>

    fetch("datos.php")
      .then(response=>response.json())
      .then(datos=>console.log(datos));

  </script>
</body>

</html>

Teniendo en cuenta que hemos creado en el servidor una aplicación en el archivo "datos.php" que genera un archivo JSON con un listado de productos:

JSON PHP

Luego mediante la llamada al método fetch se crea un objeto de tipo 'Promise', el cual tiene un método then que le debemos pasar como parámetro una función anónima que recibe en forma asíncrona la respuesta del servidor.
La respuesta la debemos convertir en nuestro caso a formato JSON, ese proceso se resuelve mediante un segundo objeto de tipo 'Promise':

    fetch("datos.php")
      .then(response=>response.json())

Como el método then retorna un nuevo objeto de tipo 'Promise' podemos encadenar una nueva llamada al método then donde procedemos a procesar el archivo JSON recuperado del servidor:

      .then(datos=>console.log(datos));

Es decir que con estas dos llamadas encadenadas al método 'then' tenemos en nuestro navegador los datos del archivo 'JSON' listo para ser procesado (en nuestro caso solo lo hemos impreso en la 'console'):

API fetch

Acotaciones

En la práctica se utilizan las llamadas encadenadas por el método 'then' con el API fetch, pero para un mayor entendimiento resolveremos el mismo problema pero de la forma larga:

  <script>
    const promesa1=window.fetch("datos.php");
    const promesa2=promesa1.then(response=>response.json());
    promesa2.then(datos=>console.log(datos));
  </script>

Como vemos llamamos al método 'fetch', recordando que es un método del objeto global 'window' y le pasamos el nombre del recurso que se encuentra en nuestro servidor web. El metodo 'fetch' retorna un objeto de tipo 'Promise' (una promesa encapsula la terminación o el fracaso de una operación asíncrona).

La terminación de la promesa se recibe en la llamada al método 'then', dicho método retorna una nueva promesa que en nuestro caso guardamos la referencia en la constante 'promesa2':

    const promesa2=promesa1.then(response=>response.json());

Nuevamente el resultado de la segunda promesa se captura en la llamada al método 'then', donde procedemos a mostrar los datos ya transformado a formato JSON que se hizo en el 'then' anterior:

    promesa2.then(datos=>console.log(datos));

Por último si no utilizamos funciones flecha el código anterior queda:

  <script>
    const promesa1 = window.fetch("datos.php");
    const promesa2 = promesa1.then(function (response) {
      return response.json()
    });
    promesa2.then(function (datos) {
      console.log(datos);
    });
  </script>

El código JavaScript anterior tiene por objetivo buscar un entendimiento de porque la llamada al método 'then' de la promesa1 recibe la respuesta del servidor y retorna una nueva promesa de convertir el flujo de datos recibidos del servidor a formato JSON. Luego el método 'then' de la segunda promesa recibe los datos en formato JSON y procede a imprimirlos.

Usaremos en los próximos conceptos el formato de llamadas encadenadas al método 'then'.

Si quiere probar la aplicación en forma local, primero debe instalar un servidor local (puede ver los pasos en el curso de PHP) y luego crear el archivo datos.php:

<?php
header('Content-Type: application/json');

function retornarConexion() {
  $server="localhost";
  $usuario="root";
  $clave="";
  $base="base1";
  $con=mysqli_connect($server,$usuario,$clave,$base) or die("problemas") ;
  mysqli_set_charset($con,'utf8'); 
  return $con;
}

$conexion = retornarConexion();

$datos = mysqli_query($conexion, "select codigo,descripcion,precio from articulos");
$resultado = mysqli_fetch_all($datos, MYSQLI_ASSOC);
echo json_encode($resultado);
?>

La tabla artículos tiene la siguiente estructura y datos iniciales:

CREATE TABLE `articulos` (
  `codigo` int(11) NOT NULL AUTO_INCREMENT,
  `descripcion` varchar(50) NOT NULL,
  `precio` float NOT NULL,
  PRIMARY KEY (`codigo`)
);

insert into `articulos` values 

(1,'peras',55),

(2,'manzanas',60),

(3,'naranjas',25),

(4,'pepino',33);

Recuperar archivo de texto con API fetch

En el concepto anterior presentamos el API fetch para recuperar datos de un servidor web. Vimos que en la primer promesa cuando se cumple procedemos a convertir los datos enviados a formato JSON:

  fetch("datos.php")
      .then(response=>response.json())
      .then(datos=>console.log(datos));

Veremos otro método que nos permite convertir los datos devueltos a formato de texto, para ello utilizamos el método 'text()' en lugar de 'json()'.

Veremos una pequeña aplicación que muestre 3 botones con diferentes signos del zodiaco, cuando se presiona el botón procedemos a requerir al servidor un archivo de texto.

pagina1.html
<!DOCTYPE html>
<html>

<head>
  <title>Ejemplo de JavaScript</title>
  <meta charset="UTF-8">
</head>

<body>
  <div>
    <button id="boton1">Aries</button>
    <button id="boton2">Tauro</button>
    <button id="boton3">Geminis</button>
  </div>
  <div id="contenido"></div>

  </div>
  <script>
    addEventListener("DOMContentLoaded", () => {
      document.getElementById("boton1").addEventListener("click", () => mostrar('aries.txt'));
      document.getElementById("boton2").addEventListener("click", () => mostrar('tauro.txt'));
      document.getElementById("boton3").addEventListener("click", () => mostrar('geminis.txt'));
    });

    function mostrar(signo) {
      fetch(signo)
        .then(response => response.text())
        .then(datos => document.getElementById("contenido").innerText = datos);
    }

  </script>

</body>

</html>

Recordar que para probar estos ejercicios debemos tener instalado un servidor web en nuestro equipo y hacer las peticiones via localhost.

En la carpeta del servidor se debe tener almacenadas los 4 archivos, el html y los 3 archivos txt:

pagina1.html
aries.txt
tauro.txt
geminis.txt

Inmediatamente la página se encuentra cargada en el navegador enlazamos el evento click para cada uno de los botones indicando que se debe llamar la función 'mostrar' con el nombre del archivo de cuenta a recuperar:

    addEventListener("DOMContentLoaded", () => {
      document.getElementById("boton1").addEventListener("click", () => mostrar('aries.txt'));
      document.getElementById("boton2").addEventListener("click", () => mostrar('tauro.txt'));
      document.getElementById("boton3").addEventListener("click", () => mostrar('geminis.txt'));
    });

La función 'mostrar' hace la petición al servidor y cuando recibe la respuesta convierte los datos recibidos a formato texto. Finalmente luego de la transformación a formato texto pasamos a mostrarlo dentro de una marca 'div':

    function mostrar(signo) {
      fetch(signo)
        .then(response => response.text())
        .then(datos => document.getElementById("contenido").innerText = datos);
    }

Nuevamente podemos comprobar la sencillez que es recuperar un recurso de nuestro servidor, convertirlo a formato texto y proceder a actualizar la página en forma dinámica.


Consumir API públicas con API fetch

Hay muchas empresas y organismos públicos que hacen públicos sus datos y permiten que otros sitios web y aplicaciones puedan consultar dicha información.

Con el API fetch podemos fácilmente acceder a las API que suministran otros sitios web.

Veamos con un ejemplo como consumimos del sitio jsonplaceholder.typicode.com/ datos ficticios sobre 10 usuarios.

Debemos conocer dos cosas para poder consumir los datos:

  1. La URL que nos suministra el recurso, en nuestro caso es:

    https://jsonplaceholder.typicode.com/users
    
  2. La estructura del archivo JSON para conocer los nombres de propiedades que accederemos:

    [
      {
        "id": 1,
        "name": "Leanne Graham",
        "username": "Bret",
        "email": "Sincere@april.biz",
        "address": {
          "street": "Kulas Light",
          "suite": "Apt. 556",
          "city": "Gwenborough",
          "zipcode": "92998-3874",
          "geo": {
            "lat": "-37.3159",
            "lng": "81.1496"
          }
        },
        "phone": "1-770-736-8031 x56442",
        "website": "hildegard.org",
        "company": {
          "name": "Romaguera-Crona",
          "catchPhrase": "Multi-layered client-server neural-net",
          "bs": "harness real-time e-markets"
        }
      },
      etc.
    

Veamos lo sencillo que es recuperar los datos de la petición mediante la API fetch:

<!DOCTYPE html>
<html>

<head>
  <title>Ejemplo de JavaScript</title>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>

<body>
  <div class="container">
    <div class="row">
      <table class="table table-striped" id="tabla1">
      </table>
    </div>
  </div>

  <script>
    addEventListener("DOMContentLoaded", () => {
      fetch("https://jsonplaceholder.typicode.com/users")
        .then(response => response.json())
        .then(datos => {
          let cad = '<tr><th>Nombre</th><th>Email</th><th>Télefono</th></tr>';
          for (let usuario of datos) {
            cad += `<tr><td>${usuario.name}</td>
            <td>${usuario.email}</td>
            <td>${usuario.phone}</td></tr>`;
          }
          document.getElementById("tabla1").innerHTML = cad;
        });
    });
  </script>

</body>

</html>

Tenemos como resultado cuando pedimos la página al servidor web:

fetch API públicas javascript

Solo a efectos que la tabla de datos se muestre con una mejor estética hemos importado de un CDN la librería CSS de Bootstrap:

  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">

Luego en el bloque de HTML hemos dispuesto una tabla HTML vacía, con la intención que en forma dinámica se carguen con los datos que recuperaremos mediante el API fetch:

  <div class="container">
    <div class="row">
      <table class="table table-striped" id="tabla1">
      </table>
    </div>
  </div>

Si se encuentra olvidado de la librería Bootstrap puede recordarlo con el curso de Bootstrap Ya.

Inmediatamente el DOM de la página se encuentra cargado por el navegador web procedemos a llamar a la función 'fetch' y le pasamos como parámetro la URL del recurso que sabemos que retorna los datos de 10 usuarios ficticios:

 
 <script>
    addEventListener("DOMContentLoaded", () => {
      fetch("https://jsonplaceholder.typicode.com/users")

Enlazamos la promesa que devuelve la función 'fetch' con la función 'then', donde procedemos pedir que se conviertan los datos recuperados a formato JSON:

        .then(response => response.json())

Finalmente llamamos al método 'then' de la segunda promesa donde disponemos la función donde concatenamos todos los datos que almacena el array almacenado en el parámetro 'datos':

        .then(datos => {
          let cad = '<tr><th>Nombre</th><th>Email</th><th>Télefono</th></tr>';
          for (let usuario of datos) {
            cad += `<tr><td>${usuario.name}</td>
            <td>${usuario.email}</td>
            <td>${usuario.phone}</td></tr>`;
          }
          document.getElementById("tabla1").innerHTML = cad;
        });
    });

Actualizamos el contenido de la 'tabla1' luego de generar el string respectivo.

Recuperar archivo de imágen con API fetch

Vimos en conceptos anteriores que la respuesta del API fetch podemos utilizar los métodos:

  • text() - Convertimos el dato devuelto a formato texto.
  • json() - Convertimos el dato devuelto a formato json.
  • blob() - Este nuevo método es utilizado entre otros propósitos para recuperar en forma asíncrona imágenes. blob significa Binary Large Objects, objetos binarios grandes.

Problema

Disponer 3 botones con diferentes signos del zodiaco, cuando se presiona el botón procedemos a requerir al servidor un archivo de imagen y proceder a mostrarlo en una etiqueta HTML 'img'.

<!DOCTYPE html>
<html>
<head>
  <title>Ejemplo de JavaScript</title>
  <meta charset="UTF-8">
</head>
<body>
  <div>
    <button id="boton1">Capricornio</button>
    <button id="boton2">Acuario</button>
    <button id="boton3">Pisis</button>
   <button id="boton4">Aries</button>
    <button id="boton5">Tauro</button>
    <button id="boton6">Geminis</button>
    <button id="boton7">Cancer</button>
    <button id="boton8">Leo</button>
    <button id="boton9">Virgo</button>
    <button id="boton10">Libra</button>
    <button id="boton11">Escorpio</button>
    <button id="boton12">Sagitario</button>
  </div>
  <img id="foto">  </div>

  <script>
      addEventListener("DOMContentLoaded", () => {
      document.getElementById("boton1").addEventListener("click", () => mostrar('imagenes/capricornio.gif'));
      document.getElementById("boton2").addEventListener("click", () => mostrar('imagenes/acuario.gif'));
      document.getElementById("boton3").addEventListener("click", () => mostrar('imagenes/pisis.gif'));
      document.getElementById("boton4").addEventListener("click", () => mostrar('imagenes/aries.gif'));
      document.getElementById("boton5").addEventListener("click", () => mostrar('imagenes/tauro.gif'));
      document.getElementById("boton6").addEventListener("click", () => mostrar('imagenes/geminis.gif'));
      document.getElementById("boton7").addEventListener("click", () => mostrar('imagenes/cancer.gif'));
     document.getElementById("boton8").addEventListener("click", () => mostrar('imagenes/leo.gif'));
      document.getElementById("boton9").addEventListener("click", () => mostrar('imagenes/virgo.gif'));
      document.getElementById("boton10").addEventListener("click", () => mostrar('imagenes/libra.gif'));
      document.getElementById("boton11").addEventListener("click", () => mostrar('imagenes/escorpio.gif'));
      document.getElementById("boton12").addEventListener("click", () => mostrar('imagenes/sagitario.gif'));

    });

    function mostrar(signo) {
      fetch(signo)
        .then(response => response.blob())
        .then(datos => document.getElementById("foto").setAttribute('src', URL.createObjectURL(datos)));
    }
  </script>
</body>
</html>


Disponemos los tres botones en el bloque HTML con una etiqueta 'img' sin definir la propiedad 'scr' (lo cual hace que en principio no aparezca una imagen):

   
  <div>
    <button id="boton1">Capricornio</button>
    <button id="boton2">Acuario</button>
    <button id="boton3">Pisis</button>
   <button id="boton4">Aries</button>
    <button id="boton5">Tauro</button>
    <button id="boton6">Geminis</button>
    <button id="boton7">Cancer</button>
    <button id="boton8">Leo</button>
    <button id="boton9">Virgo</button>
    <button id="boton10">Libra</button>
    <button id="boton11">Escorpio</button>
    <button id="boton12">Sagitario</button>
  </div>
  <img id="foto">  </div>

Cuando se presiona alguno de los botones llamamos a la función mostrar pasando como parámetro el nombre del archivo de imagen que se debe recuperar del servidor:

       addEventListener("DOMContentLoaded", () => {
      document.getElementById("boton1").addEventListener("click", () => mostrar('imagenes/capricornio.gif'));
      document.getElementById("boton2").addEventListener("click", () => mostrar('imagenes/acuario.gif'));
      document.getElementById("boton3").addEventListener("click", () => mostrar('imagenes/pisis.gif'));
	  document.getElementById("boton4").addEventListener("click", () => mostrar('imagenes/aries.gif'));
      document.getElementById("boton5").addEventListener("click", () => mostrar('imagenes/tauro.gif'));
      document.getElementById("boton6").addEventListener("click", () => mostrar('imagenes/geminis.gif'));
	  document.getElementById("boton7").addEventListener("click", () => mostrar('imagenes/cancer.gif'));
      document.getElementById("boton8").addEventListener("click", () => mostrar('imagenes/leo.gif'));
      document.getElementById("boton9").addEventListener("click", () => mostrar('imagenes/virgo.gif'));
	  document.getElementById("boton10").addEventListener("click", () => mostrar('imagenes/libra.gif'));
      document.getElementById("boton11").addEventListener("click", () => mostrar('imagenes/escorpio.gif'));
      document.getElementById("boton12").addEventListener("click", () => mostrar('imagenes/sagitario.gif'));
    });

    function mostrar(signo) {
      fetch(signo)
        .then(response => response.blob())
        .then(datos => document.getElementById("foto").setAttribute('src', URL.createObjectURL(datos)));
    }

Mediante la API fetch procedemos a solicitar en forma asíncrona que recupere el recurso (en nuestro caso solo indicamos el nombre del archivo ya que se encuentra en la misma carpeta que el archivo HTML que hace la solicitud):

    function mostrar(signo) {
      fetch(signo)

Cuando llega la respuesta del servidor procedemos a retornar a la segunda promesa los datos convertidos a formato binario mediante el método 'blob':

>
        .then(response => response.blob())

Con los datos convertidos a formato binario mediante el método createObjectURL del objeto URL procedemos a actualizar la propiedad 'src' de la etiqueta HTML 'img':

        .then(datos => document.getElementById("foto").setAttribute('src', URL.createObjectURL(datos)));

Como vemos el algoritmo es muy consiso para recuperar imágenes del servidor mediante la API fetch:

API fetch recuperar imagen javascript

Enviar datos de un formulario con la API fetch

Hemos visto en varios de los conceptos anteriores como recuperar datos con distintos formatos de un servidor web. Ahora veremos que el API fetch también nos sirve para enviar datos a un servidor web.

Implementaremos una aplicación para cargar en un formulario HTML la descripción y precio de un artículo y al presionar un botón se envíen dichos datos al servidor web.

Almacenaremos los datos en una base de datos, además implementaremos algo que ya conocemos que es la recuperación de datos de los artículos mediante una petición fetch al servidor.

El resultado final de la página es el formulario para la carga de artículos y una tabla HTML con todos los datos que se almacenan en el servidor:

fetch API enviar datos de un formulario javascript
<!DOCTYPE html>
<html>

<head>
  <title>Ejemplo de JavaScript</title>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>

<body>

  <div class="container h-100">
    <div class="row">
      <form id="formulario1">
        <div class="form-group">
          <label for="descripcion">Descripción del artículo</label>
          <input type="text" class="form-control" id="descripcion" name="descripcion" required>
        </div>
        <div class="form-group">
          <label for="precio">Precio:</label>
          <input type="number" class="form-control" id="precio" name="precio" required>
        </div>
        <div class="form-group">
          <button type="button" id="boton1" class="btn btn-primary">Nuevo artículo</button>
        </div>
      </form>

      <table class="table table-striped" id="tabla1">
      </table>
    </div>
  </div>

  <script>
    addEventListener("DOMContentLoaded", () => {
      listarArticulos();
      document.getElementById("boton1").addEventListener("click", () => agregar());
    });

    function agregar() {
      const datos = new URLSearchParams(new FormData(document.getElementById("formulario1")));
      fetch('nuevoarticulo.php', {
        method: 'POST',
        body: datos
      })
        .then(response => response.json())
        .then(datos => listarArticulos());
    }

    function listarArticulos() {
      fetch("listadoarticulos.php")
        .then(response => response.json())
        .then(datos => {
          let cad = '<tr><th>Código</th><th>Descripción</th><th>Precio</th></tr>';
          for (let articulo of datos) {
            cad += `<tr><td>${articulo.codigo}</td>
            <td>${articulo.descripcion}</td>
            <td>${articulo.precio}</td></tr>`;
          }
          document.getElementById("tabla1").innerHTML = cad;
        });
    }
  </script>

</body>

</html>

Creamos un formulario HTML donde se permite la carga de la descripción de un artículo y su precio, además definimos una marca 'button':

    <div class="row">
      <form id="formulario1">
        <div class="form-group">
          <label for="descripcion">Descripción del artículo</label>
          <input type="text" class="form-control" id="descripcion" name="descripcion" required>
        </div>
        <div class="form-group">
          <label for="precio">Precio:</label>
          <input type="number" class="form-control" id="precio" name="precio" required>
        </div>
        <div class="form-group">
          <button type="button" id="boton1" class="btn btn-primary">Nuevo artículo</button>
        </div>
      </form>

Definimos una tabla HTML vacía que la generaremos en forma dinámica cuando carguemos la página y cada vez que se ingrese un nuevo artículo:

      <table class="table table-striped" id="tabla1">
      </table>

Inmediatamente se encuentra cargada la página en el navegador procedemos a llamar a la función listarArticulos:

    addEventListener("DOMContentLoaded", () => {
      listarArticulos();
      document.getElementById("boton1").addEventListener("click", () => agregar());
    });

La función listarArticulos contiene un algoritmo que ya vimos en conceptos anteriores, donde mediante la llamada al método 'fetch' recuperamos un recurso en formato JSON con todos los datos de la tabla 'articulos' que se encuentra en el servidor:

    function listarArticulos() {
      fetch("listadoarticulos.php")
        .then(response => response.json())
        .then(datos => {
          let cad = '<tr><th>Código</th><th>Descripción</th><th>Precio</th></tr>';
          for (let articulo of datos) {
            cad += `<tr><td>${articulo.codigo}</td>
            <td>${articulo.descripcion}</td>
            <td>${articulo.precio}</td></tr>`;
          }
          document.getElementById("tabla1").innerHTML = cad;
        });
    }

Lo nuevo se presenta cuando capturamos el click del botón de 'Nuevo artículo', donde llamamos al método fetch configurando el segundo parámetro de tal forma que se adjunten en la petición al servidor los datos almacenados en el formulario:

    function agregar() {
      const datos = new URLSearchParams(new FormData(document.getElementById("formulario1")));
      fetch('nuevoarticulo.php', {
        method: 'POST',
        body: datos
      })
        .then(response => response.json())
        .then(datos => listarArticulos());
    }

El segundo parámetro del método fetch debe ser un objeto literal con la configuración de las propiedades 'method' y 'body'.

En los ejercicios anteriores no es necesario pasar este objeto ya que se encuentran configurados datos por defecto, el resultado es lo mismo si en el listadoArticulos pasamos la propiedad 'method' con el valor "GET":

function listarArticulos() {
      fetch("listadoarticulos.php",{
        method:"GET"
      })
      ...... 

Cuando se envían datos al servidor debemos configurar las propiedades 'method' con el valor 'GET' y la propiedad 'body' con un objeto 'URLSearchParams' que además recibe en el constructor la referencia de un objeto 'FormData'.

Para poder probar en forma local debemos tener los dos archivos PHP y creada la base de datos:

listadoarticulos.php

<?php
$server = "localhost";
$usuario = "root";
$clave = "";
$base = "base1";
$con = mysqli_connect($server, $usuario, $clave, $base) or die("problemas");
mysqli_set_charset($con, 'utf8');

$datos = mysqli_query($con, "select codigo,descripcion,precio from articulos");
$resultado = mysqli_fetch_all($datos, MYSQLI_ASSOC);
echo json_encode($resultado);
?>

Y por otro lado tenemos la página que contiene el algoritmo que almacena los datos del artículo en el servidor:

nuevoarticulo.php

<?php
header('Content-Type: application/json');
$server = "localhost";
$usuario = "root";
$clave = "";
$base = "base1";
$con = mysqli_connect($server, $usuario, $clave, $base) or die("problemas");
mysqli_set_charset($con, 'utf8');

mysqli_query($con, "insert into articulos(descripcion,precio) values 
                             ('$_REQUEST[descripcion]',$_REQUEST[precio])");
echo '{"resultado":"Ok"}';
?>

Enviar un archivo adjunto con la API fetch

Otra actividad común en una aplicación web es la de enviar archivos a un servidor para que sean almacenados.

Cuando necesitamos adjuntar uno o más archivos y enviarlos al servidor el API fetch requiere también que se haga por el método POST.

La siguiente página permite seleccionar un archivo y mediante 'fetch' enviar el archivo adjunto:

<!DOCTYPE html>
<html>

<head>
  <title>Ejemplo de JavaScript</title>
  <meta charset="UTF-8">
</head>

<body>
  <p>Foto:<input type="file" id="foto" required></p>
  <p><button type="button" id="boton1" >Subir foto</button></p>
  <p><img id="imagen"></p>

  <script>
    addEventListener("DOMContentLoaded", () => {
      document.getElementById("boton1").addEventListener("click", () => agregar());
    });

    function agregar() {
      let fd = new FormData();
      fd.append("foto", document.getElementById("foto").files[0]);
      fetch('subirfoto.php', {
        method: 'POST',
        body: fd
      })
        .then(response => response.json())
        .then(datos => {
          if (datos.resultado == "Ok")
            document.getElementById("imagen").setAttribute("src", document.getElementById("foto").files[0].name);
        })
    }
  </script>

</body>

</html>

Disponemos la etiqueta 'input' con el valor 'file' en la propiedad 'type':

  <p>Foto:<input type="file" id="foto" required></p>
  <p><button type="button" id="boton1" >Subir foto</button></p>
  <p><img id="imagen"></p>

Cuando se presiona el botón subir se llama a la función 'agregar' donde creamos un objeto de tipo 'FormData':

      let fd = new FormData();

Llamamos al método 'append' del FormData y asociamos un nombre en este caso "foto" y los datos del control HTML que tienen la referencia del archivo adjunto:

      fd.append("foto", document.getElementById("foto").files[0]);

Llamamos al método 'fetch' y configuramos el método de envío 'POST' y en la propiedad 'body' pasamos el objeto FormData previamente creado:

      fetch('subirfoto.php', {
        method: 'POST',
        body: fd
      })
        .then(response => response.json())

Una vez subido el archivo si se nos retorna "Ok" procedemos a mostrar la imagen, recuperando la misma del servidor donde la subimos:

        .then(datos => {
          if (datos.resultado == "Ok")
            document.getElementById("imagen").setAttribute("src", document.getElementById("foto").files[0].name);
        })
    }

La aplicación PHP que almacena la foto en el servidor es:

<?php
move_uploaded_file($_FILES['foto']['tmp_name'], $_FILES['foto']['name']);
echo '{"resultado":"Ok"}';
?>