0Pricing
Java Academy · درس

الطلبات غير المتزامنة

sendAsync وCompletableFuture

الطلبات غير المتزامنة درس مجاني في Java Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Java Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Java Academy 4 دروس في المجموع.

الطلبات غير المتزامنة

يؤدي الحجب في كل استدعاء HTTP إلى هدر مؤشرات الترابط. يوفّر عميل HTTP في JDK الدالة sendAsync، التي تعيد CompletableFuture فورًا وتنفّذ العمل باستخدام منفّذ في الخلفية.

يتيح لك ذلك إرسال العديد من الطلبات بالتزامن وضم نتائجها دون إدارة مؤشرات الترابط يدويًا.

send مقابل sendAsync

تختلف تواقيع الدالتين في القيمة التي تعيدانها:

  • send تعيد HttpResponse<T> وتحجب مؤشر الترابط، وتصرّح بالاستثناءين IOException وInterruptedException.
  • sendAsync تعيد CompletableFuture<HttpResponse<T>> ولا تحجب مؤشر الترابط مطلقًا؛ وتظهر الأخطاء من خلال future.

استدعاء أساسي للدالة sendAsync

تأخذ sendAsync الطلب نفسه وBodyHandler نفسيهما اللذين تأخذهما send. ويكتمل future المُعاد عند جاهزية الاستجابة.

import java.net.URI;
import java.net.http.*;
import java.util.concurrent.CompletableFuture;

public class Main {
    public static void main(String[] args) {
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://example.com"))
            .build();
        CompletableFuture<HttpResponse<String>> future =
            client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
        System.out.println("Request sent, future created");
    }
}

التحويل باستخدام thenApply

استخدم thenApply لتحويل النتيجة عند وصولها، مثل استخراج النص من الاستجابة.

يُنفَّذ ذلك بشكل متزامن على مؤشر الترابط الذي أكمل المرحلة السابقة، أيًا كان.

import java.util.concurrent.CompletableFuture;

public class Main {
    public static void main(String[] args) throws Exception {
        CompletableFuture<String> future =
            CompletableFuture.completedFuture("OK 200")
                .thenApply(body -> "Length=" + body.length());
        System.out.println(future.get());
    }
}

استهلاك النتيجة باستخدام thenAccept

عندما تريد تنفيذ أثر جانبي فقط دون إعادة قيمة، استخدم thenAccept. فهي تأخذ Consumer وتُنتج CompletableFuture<Void>.

import java.util.concurrent.CompletableFuture;

public class Main {
    public static void main(String[] args) throws Exception {
        CompletableFuture<Void> done =
            CompletableFuture.completedFuture("payload")
                .thenAccept(b -> System.out.println("Received: " + b));
        done.get();
    }
}

الحجب باستخدام join

للانتظار حتى ظهور نتيجة غير متزامنة من main، استدعِ join()، وهو غير مُتحقَّق منه، أو get()، وهو مُتحقَّق منه. في خادم حقيقي، ستضم المراحل بدلًا من الحجب.

تغلف join() حالات الفشل في CompletionException غير مُتحقَّق منه.

import java.util.concurrent.CompletableFuture;

public class Main {
    public static void main(String[] args) {
        CompletableFuture<Integer> f =
            CompletableFuture.supplyAsync(() -> 21).thenApply(n -> n * 2);
        int result = f.join();
        System.out.println("Result: " + result);
    }
}

معالجة الأخطاء باستخدام exceptionally

توفر exceptionally قيمة بديلة عند فشل إحدى المراحل، وبذلك تستعيد سير المعالجة.

بهذه الطريقة تمنع تدفق HTTP غير المتزامن من التوقف عند حدوث خطأ في الشبكة.

import java.util.concurrent.CompletableFuture;

public class Main {
    public static void main(String[] args) {
        CompletableFuture<String> f = CompletableFuture
            .<String>supplyAsync(() -> { throw new RuntimeException("boom"); })
            .exceptionally(ex -> "fallback: " + ex.getMessage());
        System.out.println(f.join());
    }
}

دمج طلبين

تنتظر thenCombine اكتمال futureين مستقلين ثم تدمج نتيجتيهما. ومع HTTP غير المتزامن، يتيح ذلك جلب نقطتي نهاية بالتوازي وضم نصيهما.

import java.util.concurrent.CompletableFuture;

public class Main {
    public static void main(String[] args) {
        CompletableFuture<String> a = CompletableFuture.supplyAsync(() -> "Hello");
        CompletableFuture<String> b = CompletableFuture.supplyAsync(() -> "World");
        String combined = a.thenCombine(b, (x, y) -> x + " " + y).join();
        System.out.println(combined);
    }
}

إرسال طلبات كثيرة بالتوازي

لتشغيل مجموعة من الطلبات، اجمع كل future في قائمة، ثم استخدم CompletableFuture.allOf(...) لانتظار اكتمالها جميعًا.

تعيد allOf قيمة من النوع CompletableFuture<Void>؛ وعليك قراءة النتائج الفردية بعد ذلك.

import java.util.*;
import java.util.concurrent.CompletableFuture;

public class Main {
    public static void main(String[] args) {
        List<CompletableFuture<Integer>> futures = new ArrayList<>();
        for (int i = 1; i <= 3; i++) {
            int n = i;
            futures.add(CompletableFuture.supplyAsync(() -> n * n));
        }
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        for (var f : futures) System.out.println(f.join());
    }
}

ملخص النمط غير المتزامن

يبدو نمط HTTP غير المتزامن المعتاد كما يلي:

  • client.sendAsync(req, BodyHandlers.ofString())
  • .thenApply(HttpResponse::body) للحصول على النص
  • .thenAccept(System.out::println) لاستهلاكه
  • .exceptionally(ex -> ...) للتعافي من الخطأ

لا يتم حجب أي مؤشر ترابط بانتظار الشبكة.

متى تختار التنفيذ غير المتزامن

اختر sendAsync عند إجراء العديد من الاستدعاءات المتزامنة، أو التوزيع على عدة خدمات، أو العمل داخل خادم تفاعلي أو غير حاجب. واختر send للبرامج النصية البسيطة والاستدعاءات لمرة واحدة عندما يكون الحجب مناسبًا.

تحقق سريع

اختبر مدى فهمك للطلبات غير المتزامنة.

مراجعة

لقد تعلمت إجراء استدعاءات HTTP غير حاجبة:

  • تعيد sendAsync قيمة من النوع CompletableFuture بدلًا من الحجب.
  • تعمل thenApply / thenAccept على تحويل النتيجة واستهلاكها.
  • توفر exceptionally قيمة بديلة عند الفشل.
  • تدمج thenCombine استدعاءين متوازيين، بينما تنتظر allOf اكتمال مجموعة من الاستدعاءات.
  • يناسب التنفيذ غير المتزامن الخوادم ذات التزامن العالي والخوادم التفاعلية، بينما يناسب التنفيذ المتزامن البرامج النصية البسيطة.

الأسئلة الشائعة

هل درس «الطلبات غير المتزامنة» مجاني؟

نعم — نص درس «الطلبات غير المتزامنة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Java Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Java Academy 4 دروس في المجموع.

ماذا ستتعلم في «الطلبات غير المتزامنة»؟

sendAsync وCompletableFuture تتمرن على Java Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Java Academy؟

لا تُشترط خبرة سابقة. Java Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «الطلبات غير المتزامنة»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Java Academy هذا؟

نعم. كل درس في Java Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. java.net.http.HttpClient
  2. الطلبات غير المتزامنة
  3. أجسام الطلبات والترويسات
  4. معالجة الاستجابات
← العودة إلى Java Academy