Flutter Sails.js集成插件sails_io的使用

发布于 1周前 作者 itying888 来自 Flutter

Flutter Sails.js 集成插件 sails_io 的使用

Dart/Flutter WebSocket 客户端 SDK 用于与 Sails 进行通信,适用于移动应用(或其他运行 Dart 或 Flutter 的客户端)。

使用方法

以下是一个简单的使用示例:

import 'package:sails_io/sails_io.dart';
import 'package:socket_io_client/socket_io_client.dart' as socket_io_client;

void main() {
  // 初始化 SailsIOClient
  var io = SailsIOClient(socket_io_client.io(
      'http://example_websocket_url.com?__sails_io_sdk_version=0.11.0',
      socket_io_client.OptionBuilder().setTransports(['websocket']).build()));

  // 监听连接事件
  io.socket.onConnect((_) {
    print('Connected');
  });

  // 监听自定义事件
  io.socket.on('user', (message) {});

  // 监听断开连接事件
  io.socket.onDisconnect((_) => print('disconnected'));

  // 发送 POST 请求
  io.post(
      url: 'http://example_websocket_url.com/chats',
      data: {
        'textContent': 'New chat from sails_io',
        'counterpartId': '464684932623463467'
      },
      cb: (body, jwrResponse) {
        print(body);
        print(jwrResponse.toJson());
      });
}

__sails_io_sdk_version 查询字符串

当前,Sails WebSocket 服务器期望连接的 Socket 客户端版本 >= 0.11.0,否则会默认为 0.9.0 版本。

为了覆盖这一提示,我们在连接时通过查询字符串传递版本信息,如下所示:

var io = SailsIOClient(socket_io_client.io(
    'http://example_websocket_url.com?__sails_io_sdk_version=0.11.0',
    socket_io_client.OptionBuilder().setTransports(['websocket']).build()));

请注意,这非常重要,因为即使你的 Socket 成功连接而没有该字符串,尝试监听或使用虚拟请求(如 io.postio.get)将会导致 Sails 服务器返回版本不兼容的错误。

特性与问题

请在 GitHub 问题追踪器 中提交功能请求和 bug 报告。


以下是完整的示例代码:

import 'package:sails_io/sails_io.dart';
import 'package:socket_io_client/socket_io_client.dart' as socket_io_client;

void main() {
  // 初始化 SailsIOClient
  var io = SailsIOClient(socket_io_client.io(
      'http://example_websocket_url.com?__sails_io_sdk_version=0.11.0',
      socket_io_client.OptionBuilder().setTransports(['websocket']).build()));

  // 监听连接事件
  io.socket.onConnect((_) {
    print('Connected');
  });

  // 监听自定义事件
  io.socket.on('user', (message) {});

  // 监听断开连接事件
  io.socket.onDisconnect((_) => print('disconnected'));

  // 发送 POST 请求
  io.post(
      url: 'http://example_websocket_url.com/chats',
      data: {
        'textContent': 'New chat from sails_io',
        'counterpartId': '464684932623463467'
      },
      cb: (body, jwrResponse) {
        print(body);
        print(jwrResponse.toJson());
      });
}

更多关于Flutter Sails.js集成插件sails_io的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter Sails.js集成插件sails_io的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter项目中集成Sails.js的客户端库(如sails_io)可以通过调用原生代码或使用现有的Flutter插件(如果存在)。由于sails_io是一个Node.js库,直接在Flutter中使用它并不直接可行。但是,我们可以通过平台通道(Platform Channels)来实现与原生代码的交互。

以下是一个如何在Flutter中通过平台通道与原生JavaScript代码交互的示例,这里假设你已经有一个Sails.js后端服务,并希望从Flutter应用中调用它。

步骤1:设置Sails.js后端

确保你的Sails.js后端正在运行,并且你可以通过API进行通信。

步骤2:创建Flutter项目

使用flutter create命令创建一个新的Flutter项目。

flutter create flutter_sails_io_example
cd flutter_sails_io_example

步骤3:在iOS中添加JavaScript桥接

iOS/AppDelegate.swift

AppDelegate.swift中,确保你已经配置了JavaScriptCore框架。

import UIKit
import Flutter
import WebKit
import JavaScriptCore

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

class SailsIOBridge: NSObject, FlutterPlugin {
  private var channel: FlutterMethodChannel?
  private var context: JSContext?

  public static func register(with registrar: FlutterPluginRegistrar) {
    let channel = FlutterMethodChannel(name: "flutter_sails_io", binaryMessenger: registrar.messenger())
    let instance = SailsIOBridge()
    instance.channel = channel
    registrar.addMethodCallDelegate(instance, channel: channel)
    
    // Initialize WKWebView to load JavaScript
    let webConfiguration = WKWebViewConfiguration()
    let webView = WKWebView(frame: .zero, configuration: webConfiguration)
    instance.context = webView.configuration.userContentController.javaScriptContext
    
    // Load your JavaScript file or inline script here
    if let scriptPath = Bundle.main.path(forResource: "sails_io_client", ofType: "js") {
      do {
        let scriptContent = try String(contentsOfFile: scriptPath)
        instance.context?.evaluateScript(scriptContent) { result, error in
          if let error = error {
            print("Error loading script: \(error)")
          } else {
            print("Script loaded successfully")
          }
        }
      } catch {
        print("Error reading script file: \(error)")
      }
    }
  }

  public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
    switch call.method {
    case "socketRequest":
      guard let args = call.arguments as? [String: Any],
            let url = args["url"] as? String,
            let method = args["method"] as? String,
            let data = args["data"] as? [String: Any] else {
        result(FlutterError(code: "INVALID_ARGUMENTS", message: "Invalid arguments", details: nil))
        return
      }
      
      // Assuming `io` is the Sails.io instance initialized in your JavaScript file
      let jsRequest = """
      io.socket.request({
        url: '\(url)',
        method: '\(method)',
        data: \(data)
      }, function(body, JWR){
        if (JWR.error) {
          _flutterResultError(JWR.error);
        } else {
          _flutterResultSuccess(body);
        }
      });
      """
      
      context?.evaluateScript(jsRequest) { result, error in
        if let error = error {
          print("Error evaluating script: \(error)")
          result(FlutterError(code: "EVALUATION_ERROR", message: "Error evaluating script", details: nil))
        }
      }
      
      // Placeholder functions to be implemented in native JS
      // _flutterResultSuccess and _flutterResultError should be defined in your JavaScript file
      break
    default:
      result(FlutterMethodNotImplementedError(methodName: call.method))
    }
  }

  public func dispose() {}
}

JavaScript (sails_io_client.js)

在你的iOS项目中添加一个sails_io_client.js文件,内容如下:

// Import Sails.io client library (you may need to adjust the path)
import io from 'sails.io.client';

// Configure Sails.io client
io.sails.url = 'http://localhost:1337'; // Replace with your Sails.js server URL

// Placeholder functions for Flutter communication
function _flutterResultSuccess(result) {
  // Implement native-to-Flutter communication for successful results
  // Example: window.FlutterWebViewController.sendResult(JSON.stringify(result));
}

function _flutterResultError(error) {
  // Implement native-to-Flutter communication for errors
  // Example: window.FlutterWebViewController.sendError(JSON.stringify(error));
}

注意:上面的JavaScript代码和iOS原生代码中的占位符函数(_flutterResultSuccess_flutterResultError)需要根据实际的Flutter到原生的通信机制来实现。由于Flutter与iOS WebView之间的直接通信比较复杂,这里简化为概念说明。

步骤4:在Flutter中调用原生方法

在Flutter中,你可以使用MethodChannel来调用iOS原生代码。

import 'package:flutter/services.dart';

class SailsIOClient {
  static const MethodChannel _channel = MethodChannel('flutter_sails_io');

  Future<dynamic> socketRequest(String url, String method, Map<String, dynamic> data) async {
    try {
      final result = await _channel.invokeMethod('socketRequest', {
        'url': url,
        'method': method,
        'data': data,
      });
      return result;
    } on PlatformException catch (e) {
      print("Failed to invoke: '${e.message}'.");
      return null;
    }
  }
}

步骤5:使用SailsIOClient

在你的Flutter应用中,你可以这样使用SailsIOClient

void _makeRequest() async {
  String url = '/your/sails/endpoint';
  String method = 'GET';
  Map<String, dynamic> data = {};

  dynamic result = await SailsIOClient().socketRequest(url, method, data);
  print(result);
}

注意

  • 上述代码是一个简化的示例,旨在展示如何通过平台通道在Flutter和原生代码之间通信。
  • 实际项目中,你可能需要处理更多细节,如错误处理、安全性、性能优化等。
  • 由于sails_io是Node.js库,直接在Flutter中使用并不现实。上面的示例展示了如何通过WebView和JavaScriptCore在iOS上实现这一功能,但Android的实现会有所不同,并且可能需要使用其他技术(如webview_flutter插件)。
  • 考虑使用更通用的HTTP客户端库(如diohttp)直接与Sails.js后端通信,除非你有特定的需求需要使用Sails.io客户端库的功能。
回到顶部