2015-11-26 3 views
0

Я пытаюсь сделать что-то вроде этого, я получаю информацию в массив объектов, затем я использую функцию async.each, чтобы вызвать две функции, которые отправляют данные в другой api, я использую ExpressJs. Вот код:От async.each отправьте на две функции differents

Асинхронный функция:

async.each(readingsArray, function(reading, callback) { 
    var firstTwo; 
    firstTwo = reading.value.substring(0,2); 
    if(firstTwo === '32') { 
     updateLocation(reading, function() { 
     callback(); 
     }); 
    } else { 
     updateItem(reading, function() { 
     callback(); 
     }); 
    } 
    }, function(err) { 
    if(err) { 
     res.send(Boom.badRequest('Can't sent data')); 
    } else { 
     res.send({ 
     statusCode: 200, 
     message: 'Data sent' 
     }); 
    } 
    }); 

А остальные две функции:

var updateLocation = function updateLocation (reading, callback) { 
    request.patch(config.url + '/handhelds/' + reading.id) 
    .send({ 
     //some information 
    }) 
    .end(function(err, res) { 
     if (err) { 
     callback(err); 
     } else { 
     callback(); 
     } 
    }); 
    }; 



    var updateItem = function updateItem(lectura, callback) { 
    request.post(config.url + '/items/' + reading.id + '/event') 
    .send({ 
    //some information 
    }) 
    .end(function(err, res) { 
    if (err) { 
     callback(err); 
    } else { 
     callback(); 
     } 
    }); 
}; 

Я все еще пытаюсь понять асинхронную часть nodejs. То, что я пытаюсь сделать, - это обновить местоположение устройства, после этого отправьте элементы с другой функцией updateItem до тех пор, пока не будет вызвано другое updateLocation, а затем продолжите отправку элементов. Вот почему в Async я помещаю if, если он идентифицируется из местоположения или элемента. Является ли это возможным?

EDIT1:

Вот весь код, который я использую:

'use strict'; 

var express = require('express'); 
var bodyParser = require('body-parser'); 
var request = require('superagent'); 
var async = require('async'); 
var moment = require('moment-timezone'); 
var Boom = require('boom'); 

var config = require('./config.js'); 

var app = express(); 

var getReadings = function getReadings(csvValue, mac) { 
//Here I return the array of objects 

    var readings, values; 

    var arrayFromCSV = function arrayFromCSV(csv) { 

    var array = values.replace(/\n/g, ',').replace(/\'/g, '').replace(/\"/g, '').split(','); 
    array.pop(); 
    return array; 
    }; 

    var epochToISO = function epochToISO(epochValue) { 

    var epochInMilliseconds = parseInt(epochValue, 10)/1000; 
    var date = new Date(epochInMilliseconds); 
    return date.toISOString(); 
    }; 

    var convertToArgentinaTimezone = function convertToArgTimezone(utcTime) { 

    return moment.tz(utcTime, 'America/Argentina/Buenos_Aires').format(); 
    }; 

    var separateValues = function separateValues(readings) { 

    var items = []; 
    for (var i = 0; i < lecturas.length; i += 4) { 
     var newObject = { 
     epc: lecturas[i + 1], 
     mac: mac, 
     timeStamp: convertToArgentinaTimezone(epochToISO(lecturas[i + 2])) 
     }; 
     items.push(newObject); 
    } 
    return items; 
    }; 

    lecturas = arrayFromCSV(valorCSV); 
    epcs = separarPorEPC(lecturas); 

    return epcs; 
}; 

var updateLocation = function updateLocation (reading, callback) { 
    request.patch(config.url + '/handhelds/' + reading.id) 
    .send({ 
     //some information 
    }) 
    .end(function(err, res) { 
     if (err) { 
     callback(err); 
     } else { 
     callback(); 
     } 
    }); 
    }; 

var updateItem = function updateItem(lectura, callback) { 
    request.post(config.url + '/items/' + reading.id + '/event') 
    .send({ 
    //some information 
    }) 
    .end(function(err, res) { 
    if (err) { 
     callback(err); 
    } else { 
     callback(); 
     } 
    }); 
}; 

app.use(bodyParser.urlencoded({ 
    extended: true 
})); 

app.post('/', function(req, res) { 

    var readingsInValues = req.body.field_values; 
    var mac = req.body.reader_name.replace(/\'/g, '').replace(/\"/g, ''); 
    var readingArrays = getReadings(readingsInValues, mac); 
    async.each(readingsArrays, function(reading, callback) { 
    var firstTwo; 
    firstTwo = reading.value.substring(0,2); 
    if(firstTwo === '32') { 
     updateLocation(reading, function() { 
     callback(); 
     }); 
    } else { 
     updateItem(reading, function() { 
     callback(); 
     }); 
    } 
    }, function(err) { 
    if(err) { 
     res.send(Boom.badRequest('Can't sent data')); 
    } else { 
     res.send({ 
     statusCode: 200, 
     message: 'Data sent' 
     }); 
    } 
    }); 
}); 

console.log('Traductor encendido'); 

app.listen(config.port); 

массива выглядит следующим образом:

 [ { id: '32144B5A1231200000001', 
     mac: '00:16:25:10:57:E9', 
     timeStamp: '2015-11-20T10:28:26-03:00' }, 
     { id: '30142F13F44123F0000057', 
     mac: '00:16:25:10:57:E9', 
     timeStamp: '2015-11-20T10:28:28-03:00' }, 
     { id: '32144B1231230000001AB', 
     mac: '00:16:25:10:57:E9', 
     timeStamp: '2015-11-20T10:29:09-03:00' }, 
     { id: '30142F13F0234234000055', 
     mac: '00:16:25:10:57:E9', 
     timeStamp: '2015-11-20T10:30:19-03:00' } ] 

Надеется, что это прояснить мой вопрос.

ответ

1

Я предполагаю, что ваши readingsArray могут содержать данные, такие как:

[ 
    '32_LocationA', 
    '0000_someDataAboutLocationA', 
    '0001_someDataAboutLocationA', 
    '32_LocationB', 
    '0002_someDataAboutLocationB', 
    '0003_someDataAboutLocationB' 
] 

Это 6 независимых сообщений, собранных в определенном порядке.

Что вы должны понимать, так это то, что async.each отправит ВСЕ сообщения в одно и то же время без учета заказа. Ваш оператор if просто направляет каждое сообщение на другой URL (на основе значения firstTwo). Я назову это вашим discriminatorFn.

Если вам небезразличен ORDER, вы должны предварительно обработать массив, группируя сообщения, которые должны быть в определенном порядке. Например, вы, вероятно, хотите отправить сообщение 32_LocationA перед сообщениями 0000 и 0001. То же самое с 32_LocationB и 0002 и 0003. Назовем эти «партии».

Партия может быть просто суб-массив связанных показаний, поэтому массив партий является 2D-массив, с каждой партией в «правильном» порядке:

[ 
    // batch A: 
    [ '32_LocationA', '0000...', '0001...' ], 
    // batch B: 
    [ '32_LocationB', '0002...', '0003...' ] 
] 

Для каждой партии, вы могли бы хотите убедиться, что сначала вызывается updateLocation, но вам, вероятно, не важно, какая партия идет первой (они могут быть отправлены одновременно). Это случай использования для async.each и async.eachSeries, например .:

async.each(batches, function(batch, callback) { 
    async.eachSeries(batch, discriminatorFn, callback); 
}, function(err) { 
    // results 
}); 

В eachSeries обрабатывает каждое чтение в batch массиве и ожидают функция итератора (discriminatorFn), чтобы вызвать его параметр callback перед вызовом со следующим чтением.

Надеюсь, это поможет.

Редактировать

// uses the `reduce` function to transform 
// `p` is the accumulator, "previousValue" 
// `c` is the current element of the array, "currentValue" 
var batched = readingsArray.reduce(function(p, c) { 
    if(c.value.substring(0,2) == '32') { p.push([]); } 
    p[p.length-1].push(c); 
    return p; 
}, []); 
+0

Привет Джефф, спасибо за ваш ответ, вы правы со структурой readingArray это что-то вроде этого, на мой вопрос, как я могу разделить массив в суб массивы, как вы пост? – Fernando

0

Если request от экспресс, это не для того, что вы пытаетесь сделать, так что это не будет работать. Он предназначен для размещения сервера, отвечающего на запросы клиентов.

Это поможет вам сделать http-звонки с вашего кода: https://nodejs.org/api/http.html#http_http_request_options_callback. Или вы можете использовать существующий пакет для упрощения кода (this for example)

Async не гарантирует никаких заказов на обработку показаний, вы уверены, что это то, что вы хотите?

Также вы можете упростить свой код, callback уже является функцией, поэтому вам не нужно обертывать ее внутри функции.

async.each(readingsArray, function (reading, callback) { 
    var firstTwo; 
    firstTwo = reading.value.substring(0, 2); 
    if (firstTwo === '32') { 
    updateLocation(reading, callback);  // <<<<<<<<<< here 
    } else { 
    updateItem(reading, callback);   // <<<<<<<<<< here 
    } 
}, function (err) { 
    if (err) { 
    res.send(Boom.badRequest("Can't sent data")); 
    } else { 
    res.send({ 
     statusCode: 200, 
     message: 'Data sent' 
    }); 
    } 
}); 

var updateLocation = function updateLocation(reading, callback) { 
    request.patch(config.url + '/handhelds/' + reading.id) 
    .send({ 
     //some information 
    }).end(callback);      // <<<<<<<<<< here 
}; 



var updateItem = function updateItem(lectura, callback) { 
    request.post(config.url + '/items/' + reading.id + '/event') 
    .send({ 
     //some information 
    }).end(callback);      // <<<<<<<<<< here 
}; 
+0

Я предполагаю, что он использует этот довольно популярный модуль 'request': https://github.com/request/request –

+0

Я видел, что после публикации, но я не вижу' send() 'или' end() 'методов в документе я все еще не уверен в этом объекте 'запрос'. – Shanoor

+0

Хорошая точка. Ваши комментарии действительны в любом случае. –

Смежные вопросы