Синхронные вызовы API в Node.js - PullRequest
0 голосов
/ 17 сентября 2018

У меня есть cronjob, который запускается каждые 10 секунд. Он запрашивает машины для одного клиента и выполняет вычисления на основе ответа, а затем должен обновить или создать документы с этими вычислениями в цикле for. Но вызовы API после '***' в коде не происходят до тех пор, пока не выполнится цикл for и данные, отправленные на вызовы API, не соответствуют последней машине, что является ошибкой. Я хочу решить это тем или иным способом. Мой код выглядит так:

// index.js
const cron = require("node-cron");
const express = require("express");
const fs = require("fs");
const request = require("request");

app = express();

var clientId = 'ABCD';
var apiUrl = 'http://example.com:3001/';
var getMachines                     = apiUrl + 'getMachines/',
    updateMachine                   = apiUrl + 'updateMachine/',
    getControlRoomStatus            = apiUrl + 'getControlRoomStatus/',
    registerControlRoomStatus       = apiUrl + 'registerControlRoomStatus/',
    updateControlRoomStatus         = apiUrl + 'updateControlRoomStatus/';

cron.schedule("*/10 * * * * *", function() {
    APICall(getMachines, { 'clientId' : clientId }, 'POST', function(err, machines) {
        if (err) {
            console.log(err);
        } else {
            console.log('--------------------------------------------------------------------------------------------------');
            var allMachines = machines;
            var currentDateTime = IST();
            for (var i = 0; i < 2; i++) {
                var lastCycleTime = new Date(allMachines[i]['lastCycleTime']);
                var lastHeartbeat = new Date(allMachines[i]['lastHeartbeat']);
                var machineData;
                var controlRoomData;
                var machineId = {
                    'machineId' : allMachines[i]['machineId']
                };
                console.log(machineId);
                if (allMachines[i]['downtimeStatus'] == '0') {
                    if ((currentDateTime - lastCycleTime)>300000) {
                        if ((currentDateTime - lastHeartbeat)>300000) {
                            console.log(allMachines[i]['machineId'] ,' No Internet');
                            controlRoomData = {
                                'clientId': clientId,
                                'lastTimeStamp': allMachines[i]['lastCycleTime'], 
                                'status': 'Inactive',
                                'type': 'No Internet/Power'
                            };
                        } else {
                            console.log(allMachines[i]['machineId'] ,' No button pressed');
                            controlRoomData = {
                                'clientId': clientId,
                                'lastTimeStamp': allMachines[i]['lastCycleTime'], 
                                'status': 'Inactive',
                                'type': 'No Button Pressed'
                            };
                        }
                        machineData = {
                            'status' : 'Inactive'
                        };
                    } else {
                        console.log(allMachines[i]['machineId'] ,' Active');
                        machineData = {
                            'status' : 'Active'
                        };
                        controlRoomData = {
                            'clientId': clientId,
                            'lastTimeStamp': allMachines[i]['lastCycleTime'], 
                            'status': 'Active',
                            'type': 'N.A'
                        };
                    }
                } else {
                    if ((currentDateTime - lastHeartbeat)>300000) {
                        console.log(allMachines[i]['machineId'] ,' button pressed ',' No Internet');
                        controlRoomData = {
                            'clientId': clientId,
                            'lastTimeStamp': allMachines[i]['lastCycleTime'], 
                            'status': 'Inactive',
                            'type': 'No Internet/Power'
                        };
                    } else {
                        var downtimeLength = allMachines[i]['downtimeData'].length - 1;
                        console.log(allMachines[i]['machineId'] ,' button pressed ',allMachines[i]['downtimeData'][downtimeLength]['downtimeType']);
                        controlRoomData = {
                            'clientId': clientId,
                            'lastTimeStamp': allMachines[i]['lastCycleTime'], 
                            'status': 'Inactive',
                            'type': allMachines[i]['downtimeData'][downtimeLength]['downtimeType']
                        };
                    }
                    machineData = {
                        'status' : 'Inactive'
                    };
                }
                ***
                APICall(getControlRoomStatus, machineId, 'POST', function(err, controlRoom) {
                    if (err) {
                        console.log(err);
                    } else {
                        console.log(machineId,controlRoomData);
                        if (controlRoom == null ) {
                            APICall(registerControlRoomStatus, controlRoomData, 'POST', function(err, body) {
                                if (err) {
                                    console.log(err);
                                } else {
                                    // console.log(body);
                                }
                            });
                        } else {
                            var updateControlRooomUrl = (updateControlRoomStatus+''+controlRoom['_id']+'');
                            // console.log(updateControlRooomUrl);
                            APICall(updateControlRooomUrl, controlRoomData, 'PUT', function(err, body) {
                                if (err) {
                                    console.log(err);
                                } else {
                                    // console.log(body);
                                }
                            });
                        }
                    }
                });
                var updateMachineUrl = (updateMachine+''+allMachines[i]['_id']+'');
                // console.log(updateMachineUrl);
                APICall(updateMachineUrl, machineData, 'PUT', function(err, body) {
                    if (err) {
                        console.log(err);
                    } else {
                        console.log(i,machineId);
                        // console.log(body);
                    }
                });
            }
        }
    });
});

function APICall(url, requestData, method, callback) {
    request({
        url: url,
        form: requestData,
        method: method
    }, function (error, response, body) {
        if (error || response.statusCode !== 200) {
            return callback(error || {statusCode: response.statusCode});
        }
        callback(null, JSON.parse(body));  
    });
}

function IST(){
  var dateUTC = new Date();
  var dateUTC = dateUTC.getTime(); 
  var dateIST = new Date(dateUTC);

  dateIST.setHours(dateIST.getHours() + 5); 
  dateIST.setMinutes(dateIST.getMinutes() + 30);
  return dateIST;
}

app.listen(3128);

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 18 сентября 2018

Я использовал другой метод, и теперь он работает так, как и положено.Я использовал 'async' и заменил цикл for следующим:

var async = require('async');
...
async.map(allMachines , function(machine, callback) {
...
});
...
0 голосов
/ 17 сентября 2018

Вы можете попробовать следующий пакет:

sync-request

Вы можете найти его здесь на NPM .

Вот пример того, как его использовать (издокументы):

var request = require('sync-request');
var res = request('GET', 'http://example.com');
console.log(res.getBody());

Как указано в документации, не используйте его в производственном коде , так как это ужасно заблокирует ваш сервер и значительно замедлит работу (если вызапуск HTTP-сервера, который вы используете express).

Если у вас есть асинхронный код, и вы хотите выполнить некоторый код после асинхронного, вы также можете использовать:

  • Observables (не требуется использовать собственный пакет, RxJS например)
  • Обещания (нативный ES6 JS)
...