Nadaję połączenie między nodejs i flutter ... Nadaję na kanał prywatny i słucham tego samego kanału.

Definiuję konfigurację socket.io w server.js, a następnie używam jej instancji @ authcontroller.js.

Problem polega na tym, że kiedy próbuję słuchać kanału prywatnego z auth.controller, otrzymuję odpowiedź tylko wtedy, gdy aktywnych gniazd jest więcej niż jedno gniazdo. Jednak z server.js otrzymuję odpowiedź natychmiast, nawet z tylko jednym gniazdem.

Poniżej kod:

Server.js

    //general dependencies
const port = process.env.PORT || 3000;
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);

const fileUpload = require('express-fileupload');

var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}))
const api = require('../api/AuthController')



var server = http.listen(3000, () => {
  console.log('server is running on port', server.address().port);
});


//routes
const routes = require('../api/routes');
routes(app,io);

//socket config
global.io = io; //added


    io.on('connection', function(socket){
      socket.on('privateChannelID', function (message) {
            console.log('message received from server.js')

    });
    });

AuthController.js:

global.io.on('connection', function (socket) {
         socket.on('privateChannelID', function (message) {
                    console.log('message received from authcontoller')

             });
             });

Każdy pomysł, czego mi brakuje?

Z góry dziękuję

Aktualizuj

Kod frontendowy:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:adhara_socket_io/adhara_socket_io.dart';
import 'package:geocoder/geocoder.dart';

const String URI = "http://10.0.2.2:3000/";

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  _MyHomePageState();

  List<String> toPrint = ["trying to connect"];
  SocketIOManager manager;
  Map<String, SocketIO> sockets = {};
  Map<String, bool> _isProbablyConnected = {};
  bool newtripRequest = false;
  var pickupController;
  var dropoffController;
  SocketIO socketController;
  var driver = 'driver';
  String socketIdentifier;

  @override
  void initState() {
    super.initState();
    manager = SocketIOManager();
    initSocket("default");

  }

  @override
  void dispose() {
    super.dispose();
  }




  initSocket(String identifier) async {
    setState(() => _isProbablyConnected[identifier] = true);
    SocketIO socket = await manager.createInstance(SocketOptions(
        //Socket IO server URI
        URI,
        nameSpace: (identifier == "namespaced") ? "/adhara" : "/",
        //Query params - can be used for authentication
        query: {
          "auth": "--SOME AUTH STRING---",
          "info": "new connection from adhara-socketio",
          "timestamp": DateTime.now().toString()
        },
        //Enable or disable platform channel logging
        enableLogging: false,
        transports: [
          Transports.WEB_SOCKET /*, Transports.POLLING*/
        ] //Enable required transport
        ));
    setState(() {
      socketIdentifier = identifier;
    });
    socket.onConnect((data) {
      pprint("connected...");
      pprint(data);
      sendMessage('news', 'yes', socketIdentifier);
    });

    socket.onConnectError(pprint);
    socket.onConnectTimeout(pprint);
    socket.onError(pprint);
    socket.onDisconnect(pprint);
    socket.on("news", (data) => newTripRquest(data));
    socket.connect();
    sockets[identifier] = socket;
  }

  bool isProbablyConnected(String identifier) {
    return _isProbablyConnected[identifier] ?? false;
  }

  disconnect(String identifier) async {
    await manager.clearInstance(sockets[identifier]);
    setState(() => _isProbablyConnected[identifier] = false);
  }

  sendMessage(privateChannel, messageBody, identifier) {
    //pprint("sending message from '$identifier'...");
    sockets[identifier].emit(driverChannel, [
      {'response' : messageBody}]);
    //pprint("Message emitted from '$identifier'...");
  }

  pprint(data) {
    setState(() {
      if (data is Map) {
        data = json.encode(data);
      }
      print(data);
      toPrint.add(data);
    });
  }

Aktualizacja:

AuthConroller.js

    'use strict'

    const jwt = require("jsonwebtoken");
    const bcrypt = require("bcryptjs");

    var authController = {

    findNearestDriver: function (req, res) {


        var query = Driver.find({
            'geo': {
                $near: [
                    req.body.lat,
                    req.body.lng
                ],
                // $maxDistance: distance

            }
        });
        query.exec(async function (err, driver) {
            if (err) {
                console.log(err);
                throw err;
            }

            if (!driver) {
                res.json({});
            } else {



                for (let i = 0; i < driver.length; i++) {

                    global.io.emit(`news${driver[i]._id}`, { 
               pickupLat: req.body.lat, pickupLng: req.body.lng, dropOffLat: 
               req.body.dropLat, dropOffLng: req.body.dropLng });
                    global.io.on('connection', function (socket) {
                        socket.on(`news${driver[i]._id}`, function (message) {
                            if (message.message === 'Accept') {
                                resultRecieved = true
                                console.log('message received')
                            }
                        });
                    });


                }


                res.json(driver);
            }
        });
    }
}

module.exports = authController;
0
AbdalRahman Farag 1 styczeń 2020, 22:13

1 odpowiedź

Najlepsza odpowiedź

Wewnątrz authController.js masz:

global.io.on('connection', ...)

Która jest osadzona w jakiejś innej funkcji findNearestDriver(). Tak więc ta procedura obsługi zdarzeń połączenia nie będzie aktywna, dopóki nie zostanie wywołana i wykonana funkcja findNearestDriver(), a zapytanie nie zostanie zakończone. Oznacza to, że przegapisz wszystkie zdarzenia connection, które wystąpią przed wywołaniem tej funkcji.

Jest również wewnątrz pętli for, która prawie nigdy nie jest tym, czego chcesz, ponieważ tworzy identyczne, ale zduplikowane procedury obsługi zdarzeń.

Programy obsługi zdarzeń, takie jak global.io.on('connection', ...), powinny generalnie znajdować się w pobliżu najwyższego poziomu modułu i inicjowane podczas inicjalizacji modułu, a nie w miejscu, w którym mogą być uruchamiane wiele razy.


Uwaga, ładujesz również authController.js, zanim global.io ma wartość. Oznacza to, że nie możesz po prostu przenieść global.io.on('connection', ...) na najwyższy poziom modułu, chyba że ustawisz również require('authController.js'), aby było PO global.io.

Ale myślę, że potrzebujesz trochę przeprojektowania tego, jak ta część authController.js działa, ponieważ programy obsługi zdarzeń connection muszą znajdować się na najwyższym poziomie modułu, a nie głęboko w {{X2} } pętla wewnątrz funkcji.

To dobrze ilustruje jeden z problemów związanych z używaniem zmiennych globalnych do komunikowania się, gdy występują operacje asynchroniczne. Powoduje to frustrujące problemy z synchronizacją lub kolejnością ładowania. IMO, byłoby lepiej jawnie przekazać io do tego modułu w funkcji konstruktora modułu i używać go stamtąd, a nie z globalnej. To znacznie zmniejszyłoby prawdopodobieństwo, że zakodowałbyś go w sposób, który próbuje użyć io przed zainicjalizowaniem.

0
jfriend00 1 styczeń 2020, 22:05