Creo que para responder a esta pregunta debemos comenzar con la abstracción a la que a menudo nos referimos como un patrón de diseño, y en este caso particular, el patrón de diseño “MVC”. Esto significa Modelo, Vista y Controlador, y en muchos contextos el front-end es la “Vista” (lo que ve el usuario), el back-end es el “Controlador” (lo que hace el trabajo), y la base de datos o otro almacén de datos permanente es el “Modelo” (que almacena la información para más adelante). Me gusta construir en el medio, lo que significa que primero considero lo que mi aplicación necesita HACER (como iniciar sesión en los usuarios o actualizar la información de la cuenta, o ejecutar consultas, etc.), y luego construir la lógica de negocios que utilizará para lograr esto Al hacer esto, me ayuda a definir lo que necesito almacenar (el modelo) y cómo interactuará el front-end con el back-end. Ahora, entrando en gran detalle sobre cómo se integran el front-end y el back-end.
La Vista toma muchas formas, pero en el fondo, en la web, es HTML, JavaScript y CSS. Una vista determinada (como su página de inicio o página de cuentas), o una vista parcial (tal vez su encabezado o pie de página) puede integrarse a su marco (como con las plantillas ERB en Ruby on Rails, o las plantillas Django en Django), o puede estar completamente separado (y potencialmente escrito con un marco de JavaScript front-end, como Angular, Backbone o Ember).
Esto significa que en el primer ejemplo, donde una vista se integra con el marco, a medida que se realiza una solicitud en el back-end (volveré a esto más adelante), lo que se devuelve es HTML que ha sido prestado previamente por el motor de fondo, que puede o no usar valores del controlador, e incluso puede hacer lógica usando el lenguaje de plantillas (como la plantilla ERB para Ruby on Rails o la plantilla Django en Django, como se indicó anteriormente). En el último ejemplo, todo es HTML, CSS y JavaScript (potencialmente con un marco de JavaScript), y esto cambia la forma en que el back-end devuelve datos al front-end.
- ¿Qué marcos y plataformas de servicios de back-end son la mejor combinación para un front-end de AngularJS?
- ¿Cuáles son algunas de las habilidades de configuración y desarrollo de servidores que necesito aprender para convertirme en un desarrollador de back-end?
- ¿Cuál es la forma más efectiva de convertir su backend en CRM?
- ¿Por qué los desarrolladores de backend tienen más confianza en su profesión que los desarrolladores frontend?
- Cómo aprender el desarrollo web de back-end fácilmente
Ahora, para la parte importante: ¿cómo se comunica realmente el front-end con el back-end? El front-end siempre hace una llamada , lo que significa una solicitud GET o POST en general. Una llamada puede realizarse de forma activa, haciendo clic en un enlace, en respuesta a algún evento (en JavaScript), o pasivamente (en un temporizador, también en JavaScript).
Una solicitud GET es aquella que tiene todos los valores que pasará al back-end en la propia URL (como mywebsite.com/someservice?somekey=somevalue&anotherkey=anothervalue
). En este ejemplo, cuando se realiza la llamada, realiza una solicitud de obtención al punto final “someservice” de su back-end y ha pasado los parámetros “somekey” y “anotherkey” con los valores “somevalue” y “anothervalue”.
Una solicitud POST es aquella que tiene todos los valores que pasará al back-end codificado en el cuerpo de la solicitud. En este caso, invocaría mywebsite.com/someservice
, pero los valores se codificarían en el cuerpo de la solicitud. Esto sucede cada vez que completa un formulario , en cuyo caso el cuerpo de la solicitud es contenido codificado en formularios de varias partes. Esto también se puede hacer de forma activa (p. Ej., Un usuario envía un formulario), pasivamente (p. Ej., El formulario se envía en respuesta a todos los campos que se están completando) o en un temporizador (p. Ej., El front-end comprueba el back-end para algún valor en el formulario y lo valida usando el back-end cada 5 segundos).
Y esta es la esencia de la respuesta: se realiza una llamada desde el front-end hasta el back-end a través de la interacción del usuario con la página, escuchando un evento en JavaScript o usando JavaScript como un evento cronometrado . En los tres casos tenemos una opción: ¿la solicitud será síncrona o asíncrona? Sincrónico generalmente significa que el usuario realiza una solicitud y espera la respuesta. Asíncrono generalmente significa que la solicitud se realiza en segundo plano y la página (o elementos de la página) se actualizan cuando se recibe la respuesta de la solicitud. Todas las solicitudes asincrónicas se realizan a través de solicitudes XML HTTP (XHR), que puede hacer usando JavaScript simple o cualquier marco de JavaScript (incluso jQuery lo hace muy fácil).
La siguiente gran pregunta es, ¿cómo sabe el back-end, una vez que recibe una llamada del front-end, qué hacer con esta información? Lo que sucede es esto: un back-end recibe una llamada desde el front-end (como se indicó anteriormente, usaremos la solicitud GET como ejemplo), y desarma la solicitud, clasificando lo siguiente:
- Es una solicitud GET
- El dominio es
mywebsite.com
- El puerto es 80, para http, o 443, para https (por defecto)
- El punto final es “someservice”
Luego toma esa información para enrutar la solicitud adecuadamente, pasando también el cuerpo de la solicitud. ¿Qué quiero decir con ruta? Supongamos que el back-end está configurado de una manera típica, con un servidor web (como Apache o NginX) y un servidor de aplicaciones (como Passenger o uWSGI, que montaría y proporcionaría la puerta de entrada a una aplicación Ruby on Rails o Django respectivamente). El servidor web toma esta información y, suponiendo que conoce el host y el puerto, y el recurso está permitido, pasará la información a la aplicación a través de la puerta de enlace.
Cuando la aplicación recibe la llamada, también necesita enrutar la solicitud de manera apropiada, que es donde “rutas.rb” y “http://urls.py” entran en su lugar (para Ruby on Rails y Django, respectivamente). Estos archivos dicen: si una solicitud coincide con un patrón dado (punto final, método de solicitud y, potencialmente, argumentos), entonces el enrutador debe enrutar la solicitud a un controlador y acción dados (a menudo un método dentro de un controlador dado).
Cuando el controlador recibe la solicitud, finalmente, se completa con el cuerpo de la solicitud, por lo que todas sus claves y valores pasados están presentes. La acción del controlador (su método en su controlador) realiza la “lógica de negocios”, potencialmente comunicándose con una base de datos (para almacenar o leer información), o haciendo algún cálculo, etc. Lo que es importante acerca de las diferentes formas de hacer una solicitud (sincrónicamente) o asincrónicamente) se divide en dos partes:
- ¿Qué devuelve el back-end? XML, JSON o HTML normalmente, y un solo método puede devolver cualquiera de los tres dependiendo de cómo se realizó la solicitud. Esto es lo que “responde_to” hace en Ruby on Rails, cuando se trata de una solicitud asincrónica. Renderizar y redirigir son las declaraciones que utilizamos en Ruby on Rails cuando deseamos representar una vista o redirigir a otra acción. Esto también es algo que típicamente hemos decidido a través de la arquitectura, al decidir si nuestro front-end está integrado o no como plantilla en nuestro back-end, o no. Cuando un front-end se integra como una plantilla, es posible que regresemos una vista (renderizando una vista), en cuyo caso pasamos valores a esa vista, el motor de back-end lo procesa todo como HTML, y luego se devuelve al consumidor Cuando recibimos una solicitud asincrónica, nuestro controlador debe devolver XML, JSON o HTML, dependiendo de cómo el front-end recibirá e interpretará los resultados. Un buen ejemplo de esto sería hacer una solicitud de larga duración (como una consulta de base de datos grande): el consumidor no quiere esperar para recibir una solicitud, es probable que su navegador agote el tiempo de espera antes de que se devuelva la respuesta. Como resultado, la solicitud se haría de forma asincrónica, y el usuario podría permanecer en la página y esperar una actualización, en la que el back-end devuelve un bloque de HTML, o un objeto JSON que representa los resultados de la consulta, o un temporizador podría configurarse en el front-end para escuchar dicho evento, probando el back-end periódicamente.
- Esto nos lleva a la segunda parte para hacer una solicitud: ¿qué hace el front-end con los datos devueltos? Al realizar una solicitud sincrónica, muestra esos datos (necesariamente), lo que significa que normalmente muestra una página completa, como cuando inicia sesión en un servicio y se “reenvía” a la página de su cuenta. Al realizar una solicitud asincrónica, el front-end tiene que decidir qué hacer con los resultados. Puede tomar esos resultados y mostrarlos en la página en un lugar particular (como los resultados de la consulta anterior); puede hacer cualquier cosa como resultado de o usando la respuesta del back-end.
Agreguemos un ejemplo rápido, paso a paso, para el escenario donde el usuario visita su página de inicio:
- El usuario escribe en su sitio web en la barra de URL de su navegador y presiona Intro, haciendo una solicitud GET a
mywebsite.com
- El back-end recibe esta solicitud y, conociendo el dominio, el puerto, el método y el punto final (“/”), la pasa a la aplicación
- La aplicación recibe esta solicitud y, conociendo el punto final y el método, la pasa a la acción correcta del controlador (diremos Controlador de aplicación y método de inicio)
- El método de inicio del controlador de la aplicación simplemente representa el HTML asociado a la página de inicio como una vista, pasando al HTML representado por el consumidor
- El navegador interpreta el HTML y el usuario ve la página de inicio
Hagamos un segundo escenario, uno en el que hacemos una consulta usando un formulario y luego los resultados de esa consulta deben mostrarse en un cuadro de texto en la página algún tiempo después:
- El usuario ingresa información en un formulario relacionado con su consulta (tal vez rangos de fechas o ID, etc.) y presiona el botón “enviar”
- JavaScript (que ha escrito) captura el evento (evita que ocurra el valor predeterminado), envuelve los parámetros de solicitud y realiza una solicitud POST de forma asíncrona a su punto final (diremos
mywebsite.com/query
) - El back-end recibe la solicitud y, conociendo el dominio, el puerto, el método y el punto final (“/ query”), la pasa a la aplicación
- La aplicación recibe esta solicitud y, conociendo el punto final y el método, la pasa a la acción correcta del controlador (diremos Controlador de aplicación y método de consulta)
- El método de consulta del controlador de la aplicación necesita hacer algo de lógica empresarial para iniciar la consulta y proporciona una ID de consulta, que luego vuelve al front-end como JSON (por ejemplo,
{'query_id': 1234}
) - El front-end recibe esta respuesta a través del oyente asíncrono que escribió y configura un temporizador para escuchar la finalización de la consulta
- El front-end usa JavaScript (que usted ha escrito) para hacer una solicitud POST al back-end cada 5 segundos, (diremos,
mywebsite.com/queryresults
), pasando el “query_id” que recibimos en el anterior paso como el cuerpo de la solicitud - Una vez más, el back-end enruta la solicitud de manera adecuada, esta vez a una acción del controlador que pregunta si la consulta ya se ha realizado (no voy a entrar en detalles sobre cómo hacerlo hoy)
- Si se realiza la consulta, el back-end devuelve los resultados como JSON, por ejemplo,
{'query_complete': true, 'query_results': 'somequeryresults', 'success': true, 'msg': ''}
- Si la consulta no se realiza, el back-end devuelve el mismo JSON estructurado pero con valores diferentes (tenga en cuenta que no necesita mantener la estructura, pero de nuevo no voy a entrar en el por qué de esto ahora), por ejemplo,
{'query_complete': false, 'query_results': '', 'success': false, 'msg': ''}
- También podría devolver un mensaje de error utilizando la estructura anterior, donde query_complete es verdadero, pero éxito si es falso, y un mensaje lo acompaña en el parámetro msg.
- Una vez más, el front-end debe decidir qué hacer con los resultados:
- No hace nada con los resultados si la consulta aún no se ha realizado.
- Representa los resultados en el lugar apropiado si la consulta se completa con éxito
- Le dice al usuario que hay un error cuando la consulta ha fallado, por cualquier razón
¡Espero que esto ayude!