Цепочка (или отображение) Задача, содержащая один массив данных в массив Задач
Часть изучения Fanatasy Land/Folk Tale привела меня к созданию некоторого кода. Я по сути сканирую свою сеть (через someLib) и загружаю результаты в хранилище Монго. Сканирование возвращает массив результатов, в то время как переход на монго должен работать с результатами независимо (mongoose - я тоже впервые с этой библиотекой, так что я могу ошибаться там). В традиционной обещанной базовой модели я бы
// step 0: setup
const someLibPomise = makePromiseOf(someLib)
//set 1: get data
const dataArray = yield someLibPomise()
//set 2: convert to array of promises to upsert
const promiseArray = _.map(dataArray, makeUpsertPromise)
//step 3: wait on results
const upsertResults = yield promiseArray
Само по себе это довольно чистое представление, но я хочу подтолкнуть мое понимание этих функциональных методов. Моя рабочая версия оставляет желать лучшего, поскольку я, похоже, не могу получить от Задачи, возвращенной функцией someLibTask, которая содержит массив объектов TO и массив Задач, представляющих отдельные upserts. Я чувствую, что должен быть лучший способ, вот что работает:
// step 0: setup
const someLibTask = Async.liftNode(someLib)
const cleanUpData = (dataArray) => {
return _.map(dataArray, (data) => {
// cleanup data object
return data
})
}
const upsertTask = (collection) => {
return (criteria, record) => {
return new Task( (reject, resolve) => {
const callback = (error, data) => {
if (error) reject(error)
else resolve(data)
}
collection.findOneAndUpdate(criteria, record,
{upsert: true}, callback)
})
}
}
const persist = (data) => {
mongoose.connect('mongodb://localhost/db');
const someUpsert = adapt.upsertTask(Some.collection)
const tasks = _.map(data, (record) => {
const criteria = { "id": record.id }
return serverUpsert(criteria, record)
})
return Async.parallel(tasks).fork(console.error, process.exit)
}
// step 1: make a query and return an array of objects
// () => Task(object[])
const dataTask = someLibTask().map(cleanUpData)
// step 2: for the results to error log or persist method
// (d) => (), (d) => ()
dataTask.fork(console.error, persist)
В идеале я могу связать (или отобразить) результаты из dataTask в persist, который преобразует эту отдельную задачу в массив задач upsert. Который я могу тогда ждать. Я хотел бы видеть что-то вроде:
// step 1: make a query and return an array of objects
const dataTask = someLibTask().map(cleanUpData)
// step 2: chain the results into upsert
const upsertTasks = dataTask.chain(persist)
//step 3: wait on the upsert tasks, and then log results
Async.parallel(upsertTasks).fork(console.error, process.exit)
2 ответа
получить из задачи, которая содержит массив объектов в массив задач
Это невозможно. Вы не можете выйти из Task
монада. Чтобы узнать, сколько задач вы получите в этом массиве, вам сначала нужно будет выполнить начальную задачу.
То, что вы хотите, кажется,
someLibTask().map(cleanUpData).chain(persist)
который возвращает другую задачу для результата всех upserts.
Хотелось бы получить совет о том, как это убрать дальше. Возможно, удалите карту lodash в пользу чего-то более идиоматического, а также можно ли написать финальный файл persisAllTask.fork лучше?
Настройка:
const someLibTask = Async.liftNode(someLib)
// cleanUpData :: [{}] => [{}]
const cleanUpData = (dataArray) => {
return _.map(dataArray, (data) => {
// cleanup data object
return data
})
}
// upsertTask :: {} => ( {}, {} => Task {} )
const upsertTask = (collection) => {
return (criteria, record) => {
return new Task( (reject, resolve) => {
const callback = (error, data) => {
if (error) reject(error)
else resolve(data)
}
collection.findOneAndUpdate(criteria, record,
{upsert: true}, callback)
})
}
}
// persist :: [{id :: string, ...}] => [Task {id :: string, ...}]
const persist = (data) => {
mongoose.connect('mongodb://localhost/db');
const someUpsert = upsertTask(Some.collection)
const performUpsert = (serverRecord) => {
const criteria = { "id": record.id }
return serverUpsert(criteria, serverRecord)
}
return _.map(data, performUpsert)
}
// noop :: _ => unit
const noop = () => {}
// [Task] => unit
const waitOnThenExit = (waitingOn) => {
Async.parallel(waitingOn).fork(console.error, logThenExit)
}
Процесс:
// {} => Task [{id :: string, ...}]
const dataTask = someLibTask({}).map(cleanUpData)
// Task [{id :: string, ...}] => Task [Task {id :: string, ...}]
const persistAllTask = dataTask.map(persist)
persistAllTask.fork(
noop,
waitOnThenExit)