Lập trình Flutter

Kết Nối Ứng Dụng Flutter Với API Node.js

13/11/2025 Đặng Trí Thanh 306 lượt xem ~17 phút đọc
Mục lục bài viết
    Kết Nối Ứng Dụng Flutter Với API Node.js

    Kết Nối Ứng Dụng Flutter Với API Node.js

    Flutter, một UI toolkit đến từ Google, cho phép xây dựng ứng dụng mobile, web và desktop đẹp và native từ một codebase duy nhất. Node.js là một runtime environment cho JavaScript ở phía server, rất phổ biến để xây dựng các API nhanh và có khả năng mở rộng. Việc kết hợp sức mạnh của Flutter ở frontend và Node.js ở backend tạo nên một stack phát triển hiện đại và hiệu quả.

    Bài viết này sẽ đi sâu vào cách ứng dụng Flutter của bạn có thể giao tiếp với API được xây dựng bằng Node.js, tập trung vào việc thực hiện các yêu cầu HTTP và xử lý dữ liệu.

    Sơ đồ kiến trúc tổng thể

    1. Thiết lập môi trường

    Trước khi bắt đầu code, chúng ta cần đảm bảo môi trường phát triển đã sẵn sàng.

    1.1 Chuẩn bị API Node.js

    Để làm theo hướng dẫn này, bạn cần có một API Node.js đang chạy và có thể truy cập được. Nếu bạn chưa có, bạn có thể tạo một API cơ bản rất nhanh với Express.js. Dưới đây là ví dụ về một API Node.js đơn giản trả về danh sách người dùng và cho phép thêm người dùng mới:

    const express = require('express');
    const bodyParser = require('body-parser');
    const cors = require('cors'); // Cần thiết nếu chạy Flutter app trên giả lập/thiết bị khác với server
    
    const app = express();
    const port = 3000;
    
    // Middleware
    app.use(cors());
    app.use(bodyParser.json());
    
    // Dữ liệu giả
    let users = [
      { id: 1, name: 'Alice' },
      { id: 2, name: 'Bob' }
    ];
    
    // GET request để lấy tất cả người dùng
    app.get('/api/users', (req, res) => {
      res.json(users);
    });
    
    // POST request để thêm người dùng mới
    app.post('/api/users', (req, res) => {
      const newUser = req.body;
      if (!newUser || !newUser.name) {
        return res.status(400).json({ message: 'Name is required' });
      }
      newUser.id = users.length + 1; // Tạo ID đơn giản
      users.push(newUser);
      res.status(201).json(newUser);
    });
    
    // Khởi chạy server
    app.listen(port, () => {
      console.log(`Node.js API listening at http://localhost:${port}`);
    });

    Lưu đoạn code trên vào một file (ví dụ: server.js), cài đặt các dependencies (npm install express body-parser cors) và chạy nó (node server.js). Đảm bảo API chạy trên một địa chỉ và cổng mà thiết bị Flutter của bạn có thể truy cập (ví dụ: http://10.0.2.2:3000 nếu chạy trên Android emulator và server trên localhost).

    1.2 Thiết lập Project Flutter

    Nếu bạn đã có project Flutter, hãy mở file pubspec.yaml. Nếu chưa, tạo project mới bằng flutter create your_app_name.

    Chúng ta sẽ sử dụng package http để đơn giản. Thêm http vào phần dependencies trong pubspec.yaml:

    dependencies:
      flutter:
        sdk: flutter
    
      cupertino_icons: ^1.0.2
    
      # Thêm package http tại đây
      http: ^0.13.3 # Hoặc phiên bản mới nhất
    
    dev_dependencies:
      flutter_test:
        sdk: flutter
    
      flutter_lints: ^2.0.0
    
    flutter:
      uses-material-design: true

    Sau khi thêm, chạy lệnh flutter pub get trong terminal của project Flutter để cài đặt package.

    2. Thực hiện HTTP Request từ Flutter

    Package http cung cấp các phương thức dễ sử dụng để thực hiện các yêu cầu HTTP phổ biến như GET, POST, PUT, DELETE.

    Trước tiên, import package http và dart:convert (để xử lý JSON) vào file Dart của bạn:

    import 'package:http/http.dart' as http;
    import 'dart:convert';

    Luồng HTTP Request và Response

    2.1 GET Request: Lấy dữ liệu

    Để lấy danh sách người dùng từ API Node.js ví dụ ở trên, bạn có thể tạo một hàm bất đồng bộ sử dụng http.get():

    Future<List<dynamic>> fetchUsers() async {
      final response = await http.get(Uri.parse('YOUR_NODEJS_API_URL/api/users'));
    
      if (response.statusCode == 200) {
        // Nếu server trả về mã status 200 OK, parse JSON
        return jsonDecode(response.body); // response.body là chuỗi JSON
      } else {
        // Nếu không thành công, throw một exception.
        throw Exception('Failed to load users');
      }
    }

    Bạn cần thay thế 'YOUR_NODEJS_API_URL' bằng địa chỉ IP và cổng thực tế của API Node.js server của bạn.

    2.2 POST Request: Gửi dữ liệu

    Để thêm một người dùng mới, bạn sử dụng phương thức http.post(). Bạn cần cung cấp URL, headers (để thông báo định dạng dữ liệu gửi đi là JSON) và body (dữ liệu cần gửi, đã được encode sang chuỗi JSON).

    Future<void> createUser(String name) async {
      final response = await http.post(
        Uri.parse('YOUR_NODEJS_API_URL/api/users'),
        headers: <String, String>{
          'Content-Type': 'application/json; charset=UTF-8',
        },
        body: jsonEncode(<String, String>{'name': name}),
      );
    
      if (response.statusCode == 201) {
        // Nếu server trả về mã status 201 Created
        print('User created successfully: ${response.body}');
      } else {
        // Nếu không thành công, throw một exception.
        throw Exception('Failed to create user: ${response.statusCode}');
      }
    }

    Sơ đồ luồng truyền và xử lý dữ liệu

    3. Xử lý bất đồng bộ với Async/Await

    Các thao tác mạng trong Flutter (và Dart) là bất đồng bộ. Điều này có nghĩa là chúng không chặn luồng chính của ứng dụng, giúp UI luôn mượt mà. Từ khóa async và await là cách hiện đại và dễ đọc để làm việc với các thao tác bất đồng bộ.

    • async: Được đặt trước một hàm để báo hiệu rằng hàm đó sẽ thực hiện các thao tác bất đồng bộ.
    • await: Được sử dụng bên trong một hàm async để chờ kết quả của một Future mà không chặn toàn bộ luồng thực thi. Khi gặp await, hàm sẽ tạm dừng, giải phóng CPU để làm việc khác, và sẽ tiếp tục chạy khi Future hoàn thành.

    Các ví dụ fetchUsers và createUser ở trên đều sử dụng async/await để chờ kết quả từ http.get và http.post.

    4. Xử lý lỗi và phản hồi cho người dùng

    Việc xử lý lỗi API là rất quan trọng để ứng dụng của bạn ổn định và cung cấp phản hồi rõ ràng cho người dùng. Luôn bọc các lệnh gọi API trong khối try-catch.

    void _loadUsers() async {
      try {
        List<dynamic> usersList = await fetchUsers();
        // Cập nhật UI với dữ liệu người dùng
        print('Fetched ${usersList.length} users.');
        // setState(() { _users = usersList; }); // Ví dụ cập nhật state
      } catch (e) {
        // Xử lý lỗi và thông báo cho người dùng
        print('Error fetching users: $e');
        // ScaffoldMessenger.of(context).showSnackBar(...); // Ví dụ hiển thị thông báo lỗi
      }
    }
    
    void _addUser(String name) async {
      try {
        await createUser(name);
        print('User added successfully.');
        // Có thể fetch lại danh sách người dùng sau khi thêm thành công
        // _loadUsers(); 
        // ScaffoldMessenger.of(context).showSnackBar(...); // Ví dụ hiển thị thông báo thành công
      } catch (e) {
        print('Error adding user: $e');
        // ScaffoldMessenger.of(context).showSnackBar(...); // Ví dụ hiển thị thông báo lỗi
      }
    }

    Khi server trả về mã trạng thái lỗi (ví dụ: 400, 404, 500), phương thức http.get hoặc http.post sẽ không tự động throw lỗi. Bạn cần kiểm tra thuộc tính statusCode của response và throw exception một cách thủ công nếu cần xử lý trong khối catch.

    5. Best Practices

    • Sử dụng biến môi trường: Không nên hardcode URL API trong code. Sử dụng các package như flutter_dotenv để quản lý biến môi trường.
    • Mô hình hóa dữ liệu: Thay vì làm việc trực tiếp với dynamic hoặc Map<String, dynamic>, hãy tạo các Dart class để mô hình hóa dữ liệu nhận được từ API (sử dụng json_serializable giúp tự động hóa).
    • Xử lý lỗi chi tiết: Phân loại các loại lỗi (lỗi mạng, lỗi server, lỗi parsing) và cung cấp thông báo cụ thể cho người dùng.
    • Sử dụng Dio thay vì http (Tùy chọn): Đối với các ứng dụng lớn hơn, package dio thường được ưa chuộng hơn http vì nó cung cấp nhiều tính năng hơn như interceptors, global configuration, form data, request cancellation, v.v.
    • Bảo mật: Đảm bảo kết nối API của bạn an toàn (sử dụng HTTPS). Xử lý xác thực và ủy quyền đúng cách.

    Kết luận

    Kết nối ứng dụng Flutter với API Node.js là một tác vụ phổ biến khi xây dựng các ứng dụng full-stack. Bằng cách hiểu rõ cách thực hiện HTTP requests, xử lý bất đồng bộ và quản lý lỗi trong Flutter, bạn có thể dễ dàng tích hợp ứng dụng mobile của mình với backend Node.js mạnh mẽ, mở ra nhiều khả năng phát triển ứng dụng.

    Tài Liệu Tham Khảo

    Trader hiện đại và kết nối ứng dụng

    Trader chuyên nghiệp ngày nay không chỉ đọc biểu đồ mà còn dùng kết nối ứng dụng để tự động hóa phân tích, kiểm tra chiến lược và quản lý rủi ro. Python giúp biến ý tưởng thành công cụ một cách nhanh chóng.

    Bài viết trình bày chi tiết về kết nối ứng dụng, từ thiết lập môi trường đến ví dụ áp dụng thực tế trong quy trình giao dịch hằng ngày.

    Thiết lập môi trường nhanh

    # Cài đặt các thư viện cần thiết
    pip install pandas numpy matplotlib requests
    # kiểm tra phiên bản
    import pandas as pd
    print(pd.__version__)

    Sau khi cài đặt, bạn có thể bắt đầu nạp dữ liệu giá, tính chỉ báo và vẽ biểu đồ. Quy trình lặp nhanh giúp bạn thử nghiệm nhiều ý tưởng trong thời gian ngắn.

    Các bài toán thường gặp của trader

    Bài toán Mô tả Thư viện
    Tải giá Lấy OHLCV từ sàn requests, ccxt
    Tính chỉ báo SMA, RSI, MACD pandas, ta-lib
    Backtest Mô phỏng chiến lược backtrader, vectorbt
    Cảnh báo Thông báo tín hiệu telegram, twilio
    Quản lý vốn Tính khối lượng numpy

    Ví dụ: tính RSI và phát hiện tín hiệu

    def rsi(close, period=14):
        delta = close.diff()
        gain = delta.clip(lower=0).rolling(period).mean()
        loss = (-delta.clip(upper=0)).rolling(period).mean()
        rs = gain / loss
        return 100 - (100 / (1 + rs))
    df['rsi'] = rsi(df['close'])
    print(df[['close', 'rsi']].tail())

    RSI trên 70 cho thấy vùng quá mua, dưới 30 là quá bán. Đây là tín hiệu tham khảo, cần kết hợp thêm xu hướng và khối lượng trước khi vào lệnh.

    Sai lầm phổ biến và cách tránh

    Sai lầm Vì sao nguy hiểm Cách tránh
    Dùng dữ liệu demo thay live Không đúng thực tế Kiểm tra dữ liệu thật
    Bỏ qua phí & trượt giá Lợi nhuận ảo Mô phỏng chi phí thực
    Overfitting tham số Chiến lược không ổn định Giữ tham số ít, hợp lý
    Không kiểm soát rủi ro Cháy tài khoản Đặt stop loss mọi lệnh

    Câu hỏi thường gặp về kết nối ứng dụng

    Tôi mới bắt đầu, học kết nối ứng dụng từ đâu?

    Bắt đầu từ việc nạp dữ liệu và tính chỉ báo cơ bản. Làm được hai việc này, bạn đã có nền tảng để xây dựng công cụ của riêng mình.

    Có cần giỏi toán không?

    Chỉ cần kiến thức thống kê cơ bản. Các thư viện đã đóng gói sẵn hầu hết phép tính, bạn chỉ cần hiểu ý nghĩa để dùng đúng.

    Dùng bot tự động có an toàn không?

    An toàn khi bạn hiểu rõ logic, quản lý rủi ro tốt và giám sát thường xuyên. Chạy demo trước khi dùng tiền thật.

    Kết luận

    Kết Nối Ứng Dụng giúp trader tiết kiệm thời gian, tăng độ chính xác và giảm căng thẳng. Hãy xây dựng từng bước, kiểm chứng kỹ lưỡng và luôn ưu tiên quản lý rủi ro.

    Ví dụ thực tế về kết nối ứng dụng

    Để minh họa rõ hơn, chúng ta xét một ví dụ thực tế áp dụng kết nối ứng dụng. Giả sử bạn muốn triển khai nó vào công việc hằng ngày: bắt đầu từ việc xác định mục tiêu, thu thập dữ liệu cần thiết, rồi thực hiện từng bước.

    Bước đầu tiên, hãy liệt kê các tài nguyên và công cụ bạn đang có. Bước thứ hai, xây dựng một phiên bản tối giản nhất có thể chạy được. Bước thứ ba, kiểm tra kết quả trên dữ liệu nhỏ trước khi mở rộng.

    # ví dụ tối giản: chạy thử từng bước
    def step_1():
        print('Thu thập dữ liệu')
    def step_2():
        print('Xử lý và phân tích')
    def step_3():
        print('Đánh giá kết quả')
    for f in (step_1, step_2, step_3):
        f()

    Kết quả ban đầu có thể chưa hoàn hảo, nhưng quan trọng là bạn có một vòng lặp làm → đo → học. Mỗi vòng lặp giúp bạn hiểu sâu hơn và cải thiện chất lượng.

    Điều chỉnh sau khi thử nghiệm

    Sau vòng lặp đầu tiên, hãy ghi lại những gì hoạt động tốt và những gì chưa. Dựa trên đó, điều chỉnh một tham số tại một thời điểm để dễ dàng xác định nguyên nhân của sự thay đổi.

    So sánh các cách tiếp cận kết nối ứng dụng

    Không có một cách duy nhất để áp dụng kết nối ứng dụng. Tùy vào bối cảnh, bạn có thể chọn cách làm thủ công, bán tự động hoặc tự động hoàn toàn. Mỗi cách có ưu nhược điểm riêng cần cân nhắc.

    Tiêu chí Thủ công Bán tự động Tự động
    Tốc độ Chậm Trung bình Nhanh
    Độ chính xác Phụ thuộc con người Khá ổn định Ổn định, nhất quán
    Chi phí đầu tư Thấp Trung bình Cao
    Khả năng mở rộng Hạn chế Khá tốt Rất tốt
    Rủi ro sai sót Cao Trung bình Thấp nếu đúng quy trình
    Phù hợp khi Bắt đầu, khối lượng nhỏ Đang phát triển Khối lượng lớn, dài hạn

    Lời khuyên là hãy bắt đầu với cách thủ công có hỗ trợ của công cụ, hiểu rõ quy trình, rồi mới tự động hóa từng phần. Điều này giúp bạn kiểm soát rủi ro và có nền tảng kiến thức vững chắc.

    Khi nào nên nâng cấp cách tiếp cận

    Bạn nên nâng cấp khi khối lượng công việc tăng đến mức thủ công không theo kịp, hoặc khi bạn đã hiểu đủ rõ quy trình để tin tưởng giao cho máy tính thực hiện. Đừng tự động hóa một quy trình mà bạn chưa hiểu.

    Lộ trình triển khai kết nối ứng dụng từng bước

    Việc triển khai kết nối ứng dụng hiệu quả cần một lộ trình rõ ràng. Chia nhỏ mục tiêu lớn thành các giai đoạn có thể kiểm tra được giúp bạn duy trì động lực và dễ dàng điều chỉnh khi gặp vướng mắc.

    Giai đoạn Công việc chính Kết quả mong đợi
    Tuần 1 Học khái niệm, chuẩn bị công cụ Hiểu bản chất, môi trường sẵn sàng
    Tuần 2 Xây dựng phiên bản tối giản Có sản phẩm chạy được
    Tuần 3 Kiểm thử và đánh giá Báo cáo kết quả, phát hiện lỗi
    Tuần 4 Tối ưu và mở rộng Chất lượng cải thiện rõ rệt
    Tuần 5+ Vận hành và duy trì Hệ thống ổn định, cải tiến liên tục

    Ở mỗi giai đoạn, hãy dành thời gian ghi chép lại quá trình. Nhật ký công việc không chỉ giúp bạn nhớ lại mà còn là tài liệu quý để đối chiếu khi kết quả không như mong đợi.

    Tiêu chí hoàn thành mỗi giai đoạn

    Mỗi giai đoạn nên có tiêu chí hoàn thành rõ ràng. Ví dụ: ‘có thể chạy được với dữ liệu mẫu’, ‘không còn lỗi chặn’, ‘kết quả được ghi lại’. Tiêu chí rõ ràng giúp bạn biết chính xác khi nào nên chuyển sang bước tiếp theo.

    Mẹo và thực hành tốt nhất với kết nối ứng dụng

    Áp dụng kết nối ứng dụng đúng cách sẽ giúp bạn tiết kiệm thời gian và tránh những sai lầm tốn kém. Dưới đây là những thực hành tốt nhất đúc kết từ kinh nghiệm thực tế.

    Trước hết, hãy giữ mọi thứ đơn giản. Bắt đầu với phương án đơn giản nhất đạt được mục tiêu, sau đó mới tối ưu. Sự phức tạp chỉ nên đến khi cần thiết.

    Thứ hai, luôn đo lường. Nếu bạn không đo lường được, bạn không thể cải thiện. Hãy xác định các chỉ số chính ngay từ đầu và theo dõi chúng đều đặn.

    Thứ ba, xây dựng thói quen kiểm tra định kỳ. Dành thời gian mỗi tuần để rà soát lại kết quả, phát hiện sớm những bất thường trước khi chúng trở thành vấn đề lớn.

    Thực hành Lợi ích Mức độ ưu tiên
    Giữ đơn giản Dễ hiểu, dễ bảo trì Cao
    Đo lường kết quả Cải thiện liên tục Cao
    Kiểm tra định kỳ Phát hiện sớm rủi ro Cao
    Ghi chép lại Học hỏi từ quá khứ Trung bình
    Tự động hóa dần Tiết kiệm thời gian Trung bình

    Những sai lầm phổ biến khi áp dụng kết nối ứng dụng

    Nhiều người gặp thất bại khi áp dụng kết nối ứng dụng không phải vì phương pháp sai, mà vì những sai lầm trong quá trình thực hiện. Nhận diện sớm các sai lầm này giúp bạn tránh được những tổn thất không đáng có.

    Sai lầm Hậu quả Cách khắc phục
    Thiếu kế hoạch rõ ràng Đi sai hướng, lãng phí thời gian Lập kế hoạch và mục tiêu cụ thể
    Bỏ qua dữ liệu gốc Kết luận sai lệch Kiểm tra nguồn dữ liệu kỹ lưỡng
    Quá phức tạp ban đầu Khó vận hành, dễ nản Bắt đầu tối giản
    Không kiểm tra định kỳ Rủi ro âm thầm tăng Đặt lịch kiểm tra đều đặn
    Kỳ vọng phi thực tế Thất vọng, bỏ cuộc Đặt mục tiêu thực tế, dài hạn
    Sao chép máy móc Không phù hợp hoàn cảnh Điều chỉnh theo bối cảnh

    Cách xử lý khi gặp sai lầm

    Khi phát hiện sai lầm, đừng hoảng loạn. Hãy dừng lại, xác định nguyên nhân gốc, khắc phục và rút kinh nghiệm. Ghi chép lại bài học để không lặp lại trong tương lai. Thất bại nhỏ và sớm luôn rẻ hơn thất bại lớn và muộn.

    Học Flutter bài bản

    Nếu bạn muốn học có lộ trình và có người sửa bài thay vì tự ghép tài liệu, xem khóa học Flutter Cơ Bản (28 buổi, từ con số 0 đến app đầu tiên). Chưa biết nên bắt đầu ở đâu? Đọc bài so sánh học lập trình mobile ở TPHCM.

    .hndl-embed-wrap{max-width:800px;margin:28px auto 24px}
    .hndl-embed-wrap iframe{display:block;width:100% !important;max-width:100% !important;border:0;background:#fff;height:470px}
    @media (max-width:640px){.hndl-embed-wrap iframe{height:520px}}

    Đặng Trí Thanh

    Đặng Trí Thanh

    Giám đốc Công nghệ · DNT Digital · Giảng viên HNDL Hướng Nghiệp Dữ Liệu

    836
    Bài viết
    15.4k
    Người theo dõi
    120k+
    Lượt đọc

    Đặng Trí Thanh — Founder & CTO · Hướng Nghiệp Dữ Liệu – DNT Digital. Chuyên đào tạo và triển khai thực chiến Python, MT5 và hệ thống bot auto trading / IB cho học viên và doanh nghiệp.

    document.addEventListener(‘DOMContentLoaded’, function() {
    const btn = document.getElementById(‘hndl-btn-follow’);
    const countSpan = document.getElementById(‘hndl-follower-count’);
    if (!btn || !countSpan) return;

    const authorId = ‘3’;
    const storageKey = ‘hndl_followed_author_’ + authorId;

    // Kiểm tra trạng thái đã follow từ LocalStorage
    let isFollowed = localStorage.getItem(storageKey) === ‘true’;

    function updateUI() {
    if (isFollowed) {
    btn.textContent = ‘Đang theo dõi’;
    btn.classList.add(‘active’);
    countSpan.textContent = ‘15.5k’;
    } else {
    btn.textContent = ‘Theo dõi’;
    btn.classList.remove(‘active’);
    countSpan.textContent = ‘15.4k’;
    }
    }

    updateUI();

    btn.addEventListener(‘click’, function() {
    isFollowed = !isFollowed;
    localStorage.setItem(storageKey, isFollowed ? ‘true’ : ‘false’);

    // Hiệu ứng micro-animation
    btn.style.transform = ‘scale(0.95)’;
    setTimeout(() => {
    btn.style.transform = ‘none’;
    updateUI();
    }, 100);
    });
    });

    Bài viết liên quan về Flutter

    Tham khảo thêm khóa học lập trình Flutter đa nền tảng của Hướng Nghiệp Dữ Liệu.

    .hndl-embed-wrap{max-width:800px;margin:28px auto 24px}
    .hndl-embed-wrap iframe{display:block;width:100% !important;max-width:100% !important;border:0;background:#fff;height:470px}
    @media (max-width:640px){.hndl-embed-wrap iframe{height:520px}}

    Đặng Trí Thanh

    Đặng Trí Thanh

    Giám đốc Công nghệ · DNT Digital · Giảng viên HNDL Hướng Nghiệp Dữ Liệu

    1.397
    Bài viết
    15.4k
    Người theo dõi
    120k+
    Lượt đọc

    Đặng Trí Thanh — Founder & CTO · Hướng Nghiệp Dữ Liệu – DNT Digital. Chuyên đào tạo và triển khai thực chiến Python, MT5 và hệ thống bot auto trading / IB cho học viên và doanh nghiệp.

    document.addEventListener(‘DOMContentLoaded’, function() {
    const btn = document.getElementById(‘hndl-btn-follow’);
    const countSpan = document.getElementById(‘hndl-follower-count’);
    if (!btn || !countSpan) return;

    const authorId = ‘1’;
    const storageKey = ‘hndl_followed_author_’ + authorId;

    // Kiểm tra trạng thái đã follow từ LocalStorage
    let isFollowed = localStorage.getItem(storageKey) === ‘true’;

    function updateUI() {
    if (isFollowed) {
    btn.textContent = ‘Đang theo dõi’;
    btn.classList.add(‘active’);
    countSpan.textContent = ‘15.5k’;
    } else {
    btn.textContent = ‘Theo dõi’;
    btn.classList.remove(‘active’);
    countSpan.textContent = ‘15.4k’;
    }
    }

    updateUI();

    btn.addEventListener(‘click’, function() {
    isFollowed = !isFollowed;
    localStorage.setItem(storageKey, isFollowed ? ‘true’ : ‘false’);

    // Hiệu ứng micro-animation
    btn.style.transform = ‘scale(0.95)’;
    setTimeout(() => {
    btn.style.transform = ‘none’;
    updateUI();
    }, 100);
    });
    });

    Đặng Trí Thanh

    Đặng Trí Thanh

    Giám đốc Công nghệ · DNT Digital · Giảng viên HNDL Hướng Nghiệp Dữ Liệu
    1.398 Bài viết
    15.4k Người theo dõi
    120k+ Lượt đọc

    Đặng Trí Thanh — Founder & CTO · Hướng Nghiệp Dữ Liệu - DNT Digital. Chuyên đào tạo và triển khai thực chiến Python, MT5 và hệ thống bot auto trading / IB cho học viên và doanh nghiệp.

    Bài viết liên quan

    DNT DIGITAL

    🤖 AI CODE: Vibe Code NEEDED! 🚀 🏦 SSI • DNSE • MT5 • Bitget ⚡

    Zalo 0934145100
    Khóa đào tạo
    Hỗ trợ

    Được học lại miễn phí · Hỗ trợ trọn đời · Cập nhật miễn phí

    Đội ngũ hỗ trợ

    Đặng Trí Thanh
    Đặng Trí Thanh
    Giám đốc Công nghệ DNT Digital
    Zalo 0934145100
    Mộng Cầm
    Mộng Cầm
    Hỗ trợ khách hàng · Huấn luyện viên
    Zalo 0927909257
    Khánh Linh
    Khánh Linh
    Hỗ trợ khách hàng · Huấn luyện viên
    Zalo 0927909582