从async.each发送到两个不同的函数

时间:2015-11-26 04:10:11

标签: javascript node.js asynchronous

我试图做这样的事情,我收到一个对象数组的信息,然后我使用async.each函数,调用两个函数将数据发送到另一个api,我' m使用ExpressJs。这是代码:

异步功能:

 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被调用,然后继续发送项目。这就是为什么在异步我把一个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' } ]

希望这能澄清我的问题。

2 个答案:

答案 0 :(得分:1)

我假设您的readingsArray可能包含以下数据:

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

这些是6个独立的消息,按某种顺序收集。

您应该了解的是async.each将同时发送所有消息,而不考虑订单。您的if语句只是将每条消息路由到不同的URL(基于firstTwo值)。我将此称为discriminatorFn

如果您关心ORDER,则应该通过对需要按特定顺序进行分组的消息进行分组来预处理数组。例如,您可能希望在32_LocationA0000消息之前发送0001消息。与32_LocationB0002以及0003相同。让我们称这些&#34;批次&#34;。

批次可能只是相关读数的子数组,因此批次数组是一个2D数组,每个批次都在&#34;右边&#34;顺序:

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

对于每个批次,您可能希望确保首先调用updateLocation,但您可能不关心哪个批次首先(它们可以同时发送)。这是async.eachasync.eachSeries的用例,例如:

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

eachSeries处理batch数组中的每个读取并等待迭代器函数(discriminatorFn)调用其callback参数,然后再调用下一个读数。< / p>

希望这有帮助。

修改

// 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;
}, []);

答案 1 :(得分:0)

如果request来自Express,则不是您要尝试的内容,因此无效。它用于托管服务器以回答客户端请求。

这有助于您通过代码进行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
};