Чтобы продемонстрировать будущее в JavaScript, я буду ссылаться на библиотеку Fluture. Фэнтезийная земля, соответствующая монадической альтернативе обещаниям.
Fluture предлагает структуру управления, аналогичную обещаниям. Подобно обещаниям, фьючерсы представляют ценность, возникающую в результате успеха или неудачи асинхронной операции (I/O).
Получение значения с конечной точки с использованием обещания – довольно тривиальная операция.
Это может выглядеть примерно так.
import axios from "axios";
var getToDo = id => axios.get(`https://jsonplaceholder.typicode.com/todos/${id}`)
getToDo(1)
.then(({data}) => data)
.catch(e => e)
// { userId: 1, id: 1, title: 'delectus autautem', completed: false }
Получение ценности с конечной точки с использованием будущего также довольно тривиально. Похоже, это.
import axios from "axios";
import { tryP } from "fluture";
var getToDo = id =>
tryP(() => axios.get(`https://jsonplaceholder.typicode.com/todos/${id}`))
getToDo(1).fork(err => err, ({ data }) => data)
// { userId: 1, id: 1, title: 'delectus autautem', completed: false }
Что -то, чтобы отметить. Чтобы получить результат будущего, мы должны распаться. Левая сторона нашей вилки будет работать, если есть ошибка, похожая на ловушку. Правая сторона нашей вилки будет содержать наш результат, аналогичный тогда.
Фьючерсы позволяют нам цеплять и сопоставлять свои результаты в другие будущие или выполнять манипулирование данными в результатах будущего, прежде чем возвращаться, а также улавливать ошибки и управление тем, прежде чем фактически разбивать.
Вот пример.
import { tryP, of, ap } from "fluture";
import axios from "axios";
const loginRequest = email => password =>
tryP(() =>
axios({
url :`https://www.fake.com/login`,
data : { email, password }
})
)
const userDetailsRequest = id =>
tryP(() => axios.get(`https://www.fake.com/userDetails/${id}`))
const login = email => password => loginRequest(email)(password)
.chain({ data }) => userDetailsRequest(data.id))
.map(({ data }) => formatData(data))
.mapRej(err => formatError(err))
login('faker@gmail.com')('admin123').fork(err => err, userDetails => userDetails)
Разница между. и .chainrej
- Цепочка: результат
.chainдолжно быть будущее - Карта: результат
.картане будущее - Maprej: результат
.maprejне является будущим и будет вызвано только в случае неудачи будущего - Chainrej: результат
.chainrejДолжен быть будущее и будет только запустить Если будущее выйдет из строя
Если будущее не удастся/ошибки, это «короткое замыкание» .map и .цепь не будет запущен, поток будет направлен на либо Анкет Maprej или .chainrej в каком бы то ни было программист.
Теперь к чему -то немного сложнее.
Недавно меня попросили написать программу, которая принесла комментарии для сообщения в блоге. Был запрос, который вернул сообщение в блоге, и он включал в себя множество удостоверений личности. Каждый идентификатор представлял комментарий. Каждый комментарий требовал его собственного запроса.
Итак, представьте, что вам нужно сделать 100 запросов, чтобы вернуть 100 комментариев.
(Параллель) [https://github.com/fluture-js/fluture/tree/11.x#parallel]
Fluture имеет API под названием параллель
Параллель позволяет нам выполнять несколько асинхронных запросов одновременно, заставить их разрешить в любом случае и возвращать нам результаты после завершения всех запросов.
Вот как это выглядело бы.
import { tryP, parallel } from "fluture";
import axios from "axios";
// Our Future
const getCommentRequest = comment_id =>
tryP(() => axios.get(`https://www.fake-comments.com/id/${comment_id}`))
.map(({ data }) => data);
// comments is an array of ID's
const getComments = comments =>
parallel(Infinity, comments.map(getCommentRequest))
// Infinity will allow any number of requests to be fired simultaneously, returning us the results once all requests have completed.
// The result here will be an array containing the response from each request.
getComments.fork(err => err, comments => comments)
Замена бесконечности на число. С, скажем, 10, будет извлекать 10 комментариев за раз, разрешив, когда были получены все комментарии в массиве.
В следующем примере представьте себе случай, когда могут получить некоторые данные, которые полезны для нас только в случае успеха некоторых первоначальных запросов.
(AP) [https://github.com/fluture-js/fluture/tree/11.x#ap]
Применяет функцию, содержащуюся в левом будущем, к значению, содержащемуся в правом будущем. Если один из будущих отклонит, результирующее будущее также будет отклонено.
Допустим, нам нужно получить учетную запись пользователя. Если учетная запись найдена, мы можем попытаться завести их друзей. Если мы найдем их друзей, мы можем попытаться забрать фотографии их друга. Если какой -либо из этих запросов не удастся, их короткие замыкания по потоку, и мы упали бы в левую сторону нашей вилки, где мы можем обработать ошибку.
import { tryP, of, ap } from "fluture";
import axios from "axios";
// Our Futures
const retrieveUserAccount = id =>
tryP(() => axios.get(`https://www.fake.com/user/${id}`))
const retrieveUserFriends = id =>
tryP(() => axios.get(`https://www.fake.com/friends/${id}`))
const retrieveUserFriendsPhotos = id =>
tryP(() => axios.get(`https://www.fake.com/friendsPhotos/${id}`))
const retrieveUserInformation = id =>
of(account =>
friends =>
friendsPhotos => {account, friends, friendsPhotos}) //All results returned
.ap(retrieveUserFriendsPhotos(id)) // 3rd
.ap(retrieveUserFriends(id)) // 2nd
.ap(retrieveUserAccount(id)) // Fired 1st
retrieveUserInformation.fork(err => err, results => results)
Фьючерсы позволяют нам хорошо составить наши асинхронные операции.
(Дополнительная информация о фрукторах) [ https://github.com/fluture-js/fluture/tree/11.x ]
Спасибо за чтение!
Оригинал: “https://dev.to/vageez/using-futures-to-handle-complex-asynchronous-operations-in-javascript-24oh”