Join us for Firebase Summit on November 10, 2021. Tune in to learn how Firebase can help you accelerate app development, release with confidence, and scale with ease. Register

Gọi các chức năng từ ứng dụng của bạn

Chức năng đám mây cho SDK ứng dụng khách Firebase cho phép bạn gọi các chức năng trực tiếp từ ứng dụng Firebase. Để gọi một hàm từ ứng dụng của bạn theo cách này, hãy viết và triển khai một hàm HTTPS Callable trong Cloud Functions, sau đó thêm logic ứng dụng khách để gọi hàm từ ứng dụng của bạn.

Điều quan trọng là cần lưu ý rằng HTTPS chức năng callable là chức năng tương tự nhưng không giống với HTTP. Để sử dụng chức năng HTTPS callable bạn phải sử dụng SDK khách hàng cho nền tảng của bạn cùng với functions.https backend API (hoặc thực hiện các giao thức). Các hàm có thể gọi có sự khác biệt chính sau các hàm HTTP:

  • Với khả năng gọi, mã thông báo Xác thực Firebase, mã thông báo FCM và mã thông báo Kiểm tra ứng dụng, khi có sẵn, sẽ tự động được đưa vào yêu cầu.
  • Các functions.https.onCall kích hoạt tự động deserializes cơ thể yêu cầu và xác nhận auth thẻ.

SDK Firebase cho Chức năng đám mây v0.9.1 trở lên tương tác với các phiên bản tối thiểu SDK ứng dụng khách Firebase này để hỗ trợ các chức năng HTTPS Callable:

  • SDK Firebase dành cho iOS 8.8.0
  • SDK Firebase dành cho Android 20.0.1
  • SDK JavaScript của Firebase 8.10.0
  • Firebase Modular Web SDK phiên bản 9.0

Nếu bạn muốn thêm chức năng tương tự như một ứng dụng được xây dựng trên một nền tảng được hỗ trợ, vui lòng xem Nghị định thư số kỹ thuật cho https.onCall . Phần còn lại của hướng dẫn này cung cấp hướng dẫn về cách viết, triển khai và gọi một hàm có thể gọi HTTPS cho iOS, Android, web, C ++ và Unity.

Viết và triển khai hàm có thể gọi

Sử dụng functions.https.onCall để tạo ra một HTTPS chức năng callable. Phương pháp này có hai tham số: data , và tùy chọn context :

// Saves a message to the Firebase Realtime Database but sanitizes the text by removing swearwords.
exports.addMessage = functions.https.onCall((data, context) => {
  // ...
});

Đối với một hàm có thể được gọi là tiết kiệm một tin nhắn văn bản đến cơ sở dữ liệu thời gian thực, ví dụ, data có thể chứa nội dung tin nhắn, trong khi context các thông số thể hiện thông tin auth người sử dụng:

// Message text passed from the client.
const text = data.text;
// Authentication / user information is automatically added to the request.
const uid = context.auth.uid;
const name = context.auth.token.name || null;
const picture = context.auth.token.picture || null;
const email = context.auth.token.email || null;

Khoảng cách giữa vị trí của chức năng có thể gọi và vị trí của ứng dụng khách đang gọi có thể tạo ra độ trễ mạng. Để hiệu suất tối ưu hóa, hãy cân nhắc xác định vị trí chức năng nếu có thể, và hãy chắc chắn để sắp xếp vị trí của callable với các thiết lập vị trí khi bạn khởi SDK về phía khách hàng.

Theo tùy chọn, bạn có thể đính kèm chứng thực Kiểm tra ứng dụng để giúp bảo vệ tài nguyên phụ trợ của bạn khỏi bị lạm dụng, chẳng hạn như gian lận thanh toán hoặc lừa đảo. Xem Enable App Kiểm tra thực thi pháp Cloud Chức năng .

Gửi lại kết quả

Để gửi dữ liệu trở lại máy khách, hãy trả lại dữ liệu có thể được mã hóa JSON. Ví dụ, để trả về kết quả của một phép toán cộng:

// returning result.
return {
  firstNumber: firstNumber,
  secondNumber: secondNumber,
  operator: '+',
  operationResult: firstNumber + secondNumber,
};

Để trả về dữ liệu sau một hoạt động không đồng bộ, hãy trả về một lời hứa. Dữ liệu được trả về bởi lời hứa sẽ được gửi lại cho khách hàng. Ví dụ: bạn có thể trả về văn bản được làm sạch mà hàm có thể gọi đã ghi vào Cơ sở dữ liệu thời gian thực:

// Saving the new message to the Realtime Database.
const sanitizedMessage = sanitizer.sanitizeText(text); // Sanitize the message.
return admin.database().ref('/messages').push({
  text: sanitizedMessage,
  author: { uid, name, picture, email },
}).then(() => {
  console.log('New Message written');
  // Returning the sanitized message to the client.
  return { text: sanitizedMessage };
})

Xử lý lỗi

Để đảm bảo khách hàng được chi tiết lỗi hữu ích, lỗi trở về từ một callable bằng cách ném (hoặc trả lại một Promise bị từ chối với) một thể hiện của functions.https.HttpsError . Các lỗi có code thuộc tính có thể là một trong những giá trị niêm yết tại functions.https.HttpsError . Các lỗi cũng có một chuỗi message , mặc định là một chuỗi rỗng. Họ cũng có thể có một tùy chọn details lĩnh vực với một giá trị tùy ý. Nếu một khác lỗi hơn HttpsError được ném từ chức năng của mình, khách hàng của bạn thay vì nhận lỗi với thông điệp INTERNAL và mã internal .

Ví dụ: một hàm có thể đưa ra các lỗi xác thực và xác thực dữ liệu với các thông báo lỗi để trả về ứng dụng khách đang gọi:

// Checking attribute.
if (!(typeof text === 'string') || text.length === 0) {
  // Throwing an HttpsError so that the client gets the error details.
  throw new functions.https.HttpsError('invalid-argument', 'The function must be called with ' +
      'one arguments "text" containing the message text to add.');
}
// Checking that the user is authenticated.
if (!context.auth) {
  // Throwing an HttpsError so that the client gets the error details.
  throw new functions.https.HttpsError('failed-precondition', 'The function must be called ' +
      'while authenticated.');
}

Triển khai chức năng có thể gọi

Sau khi bạn lưu một hàm callable hoàn tất trong vòng index.js , nó được triển khai cùng với tất cả các chức năng khác khi bạn chạy firebase deploy . Để triển khai chỉ có thể được gọi, sử dụng --only lập luận như để thực hiện triển khai một phần :

$ firebase deploy --only functions:addMessage

Nếu bạn gặp lỗi khi cho phép triển khai chức năng, chắc chắn rằng phù hợp vai trò IAM được gán cho người dùng chạy các lệnh triển khai.

Thiết lập môi trường phát triển khách hàng của bạn

Đảm bảo rằng bạn đáp ứng bất kỳ điều kiện tiên quyết nào, sau đó thêm các phụ thuộc bắt buộc và thư viện ứng dụng khách vào ứng dụng của bạn.

iOS

  1. Thực hiện theo các hướng dẫn để thêm căn cứ hỏa lực để ứng dụng iOS của bạn .
  2. Thêm Cloud Chức năng pod để bạn Podfile :
    pod 'Firebase/Functions'
  3. Lưu tập tin, sau đó chạy:
    pod install

Phiên bản web 9

  1. Thực hiện theo các hướng dẫn để thêm căn cứ hỏa lực để ứng dụng web của bạn . Hãy chắc chắn để chạy lệnh sau đây từ thiết bị đầu cuối của bạn:
    npm install firebase@9.1.3 --save
    
  2. Yêu cầu thủ công cả lõi Firebase và Chức năng đám mây:

     import { initializeApp } from 'firebase/app';
     import { getFunctions } from 'firebase/functions';
    
     const app = initializeApp({
         projectId: '### CLOUD FUNCTIONS PROJECT ID ###',
         apiKey: '### FIREBASE API KEY ###',
         authDomain: '### FIREBASE AUTH DOMAIN ###',
       });
     const functions = getFunctions(app);
    

Phiên bản web 8

  1. Thực hiện theo các hướng dẫn để thêm căn cứ hỏa lực để ứng dụng web của bạn .
  2. Thêm cốt lõi căn cứ hỏa lực và Cloud thư viện chức năng khách hàng để ứng dụng của bạn:
    <script src="https://www.gstatic.com/firebasejs/8.10.0/firebase.js"></script>
    <script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-functions.js"></script>
    

SDK chức năng đám mây cũng có sẵn dưới dạng gói npm.

  1. Chạy lệnh sau đây từ thiết bị đầu cuối của bạn:
    npm install firebase@8.10.0 --save
    
  2. Bằng tay đòi hỏi cả hai căn cứ hỏa lực cốt lõi và chức năng Cloud:
    const firebase = require("firebase");
    // Required for side-effects
    require("firebase/functions");
    

Java

  1. Thực hiện theo các hướng dẫn để thêm căn cứ hỏa lực để ứng dụng Android của bạn .

  2. Sử dụng các căn cứ hỏa lực Android HĐQT , kê khai phụ thuộc cho Cloud Chức năng thư viện Android trong module của bạn (ứng dụng cấp) tập tin Gradle (thường là app/build.gradle ).

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:28.4.2')
    
        // Declare the dependency for the Cloud Functions library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-functions'
    }
    

    Bằng việc sử dụng căn cứ hỏa lực Android HĐQT , ứng dụng của bạn sẽ luôn luôn sử dụng các phiên bản tương thích của các thư viện căn cứ hỏa lực Android.

    (Alternative) Khai báo căn cứ hỏa lực phụ thuộc thư viện mà không sử dụng HĐQT

    Nếu bạn chọn không sử dụng Firebase BoM, bạn phải chỉ định từng phiên bản thư viện Firebase trong dòng phụ thuộc của nó.

    Lưu ý rằng nếu bạn sử dụng nhiều thư viện căn cứ hỏa lực trong ứng dụng của bạn, chúng tôi khuyên bạn nên sử dụng HĐQT để quản lý các phiên bản thư viện, đảm bảo rằng tất cả các phiên bản tương thích.

    dependencies {
        // Declare the dependency for the Cloud Functions library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-functions:20.0.1'
    }
    

Kotlin + KTX

  1. Thực hiện theo các hướng dẫn để thêm căn cứ hỏa lực để ứng dụng Android của bạn .

  2. Sử dụng các căn cứ hỏa lực Android HĐQT , kê khai phụ thuộc cho Cloud Chức năng thư viện Android trong module của bạn (ứng dụng cấp) tập tin Gradle (thường là app/build.gradle ).

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:28.4.2')
    
        // Declare the dependency for the Cloud Functions library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-functions-ktx'
    }
    

    Bằng việc sử dụng căn cứ hỏa lực Android HĐQT , ứng dụng của bạn sẽ luôn luôn sử dụng các phiên bản tương thích của các thư viện căn cứ hỏa lực Android.

    (Alternative) Khai báo căn cứ hỏa lực phụ thuộc thư viện mà không sử dụng HĐQT

    Nếu bạn chọn không sử dụng Firebase BoM, bạn phải chỉ định từng phiên bản thư viện Firebase trong dòng phụ thuộc của nó.

    Lưu ý rằng nếu bạn sử dụng nhiều thư viện căn cứ hỏa lực trong ứng dụng của bạn, chúng tôi khuyên bạn nên sử dụng HĐQT để quản lý các phiên bản thư viện, đảm bảo rằng tất cả các phiên bản tương thích.

    dependencies {
        // Declare the dependency for the Cloud Functions library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation 'com.google.firebase:firebase-functions-ktx:20.0.1'
    }
    

C ++

Đối với C ++ với Android:

  1. Thực hiện theo các hướng dẫn để thêm căn cứ hỏa lực để ++ Dự án C của bạn .
  2. Thêm firebase_functions thư viện để bạn CMakeLists.txt tập tin.

Đối với C ++ với iOS:

  1. Thực hiện theo các hướng dẫn để thêm căn cứ hỏa lực để ++ Dự án C của bạn .
  2. Thêm Cloud Chức năng pod để bạn Podfile :
    pod 'Firebase/Functions'
  3. Lưu tập tin, sau đó chạy:
    pod install
  4. Thêm cốt lõi căn cứ hỏa lực và Cloud Chức năng khung từ căn cứ hỏa lực C ++ SDK cho dự án Xcode của bạn.
    • firebase.framework
    • firebase_functions.framework

Đoàn kết

  1. Thực hiện theo các hướng dẫn để thêm căn cứ hỏa lực cho dự án Unity của bạn .
  2. Thêm FirebaseFunctions.unitypackage từ căn cứ hỏa lực Unity SDK cho dự án Unity của bạn.

Khởi tạo SDK máy khách

Khởi tạo một phiên bản của Chức năng đám mây:

Nhanh

lazy var functions = Functions.functions()

Objective-C

@property(strong, nonatomic) FIRFunctions *functions;
// ...
self.functions = [FIRFunctions functions];

Phiên bản web 8

firebase.initializeApp({
  apiKey: '### FIREBASE API KEY ###',
  authDomain: '### FIREBASE AUTH DOMAIN ###',
  projectId: '### CLOUD FUNCTIONS PROJECT ID ###'
  databaseURL: 'https://### YOUR DATABASE NAME ###.firebaseio.com',
});

// Initialize Cloud Functions through Firebase
var functions = firebase.functions();

Phiên bản web 9

const app = initializeApp({
  projectId: '### CLOUD FUNCTIONS PROJECT ID ###',
  apiKey: '### FIREBASE API KEY ###',
  authDomain: '### FIREBASE AUTH DOMAIN ###',
});
const functions = getFunctions(app);

Java

private FirebaseFunctions mFunctions;
// ...
mFunctions = FirebaseFunctions.getInstance();

Kotlin + KTX

private lateinit var functions: FirebaseFunctions
// ...
functions = Firebase.functions

C ++

firebase::functions::Functions* functions;
// ...
functions = firebase::functions::Functions::GetInstance(app);

Đoàn kết

functions = Firebase.Functions.DefaultInstance;

Gọi hàm

Nhanh

functions.httpsCallable("addMessage").call(["text": inputField.text]) { result, error in
  if let error = error as NSError? {
    if error.domain == FunctionsErrorDomain {
      let code = FunctionsErrorCode(rawValue: error.code)
      let message = error.localizedDescription
      let details = error.userInfo[FunctionsErrorDetailsKey]
    }
    // ...
  }
  if let data = result?.data as? [String: Any], let text = data["text"] as? String {
    self.resultField.text = text
  }
}

Objective-C

[[_functions HTTPSCallableWithName:@"addMessage"] callWithObject:@{@"text": _inputField.text}
                                                      completion:^(FIRHTTPSCallableResult * _Nullable result, NSError * _Nullable error) {
  if (error) {
    if (error.domain == FIRFunctionsErrorDomain) {
      FIRFunctionsErrorCode code = error.code;
      NSString *message = error.localizedDescription;
      NSObject *details = error.userInfo[FIRFunctionsErrorDetailsKey];
    }
    // ...
  }
  self->_resultField.text = result.data[@"text"];
}];

Phiên bản web 8

var addMessage = firebase.functions().httpsCallable('addMessage');
addMessage({ text: messageText })
  .then((result) => {
    // Read result of the Cloud Function.
    var sanitizedMessage = result.data.text;
  });

Phiên bản web 9

import { getFunctions, httpsCallable } from "firebase/functions";

const functions = getFunctions();
const addMessage = httpsCallable(functions, 'addMessage');
addMessage({ text: messageText })
  .then((result) => {
    // Read result of the Cloud Function.
    /** @type {any} */
    const data = result.data;
    const sanitizedMessage = data.text;
  });

Java

private Task<String> addMessage(String text) {
    // Create the arguments to the callable function.
    Map<String, Object> data = new HashMap<>();
    data.put("text", text);
    data.put("push", true);

    return mFunctions
            .getHttpsCallable("addMessage")
            .call(data)
            .continueWith(new Continuation<HttpsCallableResult, String>() {
                @Override
                public String then(@NonNull Task<HttpsCallableResult> task) throws Exception {
                    // This continuation runs on either success or failure, but if the task
                    // has failed then getResult() will throw an Exception which will be
                    // propagated down.
                    String result = (String) task.getResult().getData();
                    return result;
                }
            });
}

Kotlin + KTX

private fun addMessage(text: String): Task<String> {
    // Create the arguments to the callable function.
    val data = hashMapOf(
        "text" to text,
        "push" to true
    )

    return functions
            .getHttpsCallable("addMessage")
            .call(data)
            .continueWith { task ->
                // This continuation runs on either success or failure, but if the task
                // has failed then result will throw an Exception which will be
                // propagated down.
                val result = task.result?.data as String
                result
            }
}

C ++

firebase::Future<firebase::functions::HttpsCallableResult> AddMessage(
    const std::string& text) {
  // Create the arguments to the callable function.
  firebase::Variant data = firebase::Variant::EmptyMap();
  data.map()["text"] = firebase::Variant(text);
  data.map()["push"] = true;

  // Call the function and add a callback for the result.
  firebase::functions::HttpsCallableReference doSomething =
      functions->GetHttpsCallable("addMessage");
  return doSomething.Call(data);
}

Đoàn kết

private Task<string> addMessage(string text) {
  // Create the arguments to the callable function.
  var data = new Dictionary<string, object>();
  data["text"] = text;
  data["push"] = true;

  // Call the function and extract the operation from the result.
  var function = functions.GetHttpsCallable("addMessage");
  return function.CallAsync(data).ContinueWith((task) => {
    return (string) task.Result.Data;
  });
}

Xử lý lỗi trên máy khách

Máy khách nhận được lỗi nếu máy chủ gặp lỗi hoặc nếu lời hứa kết quả bị từ chối.

Nếu lỗi trả về của hàm là loại function.https.HttpsError , sau đó khách hàng nhận được các lỗi code , message , và details từ các lỗi máy chủ. Nếu không, các lỗi chứa thông điệp INTERNAL và mã INTERNAL . Xem hướng dẫn làm thế nào để xử lý các lỗi trong chức năng callable của bạn.

Nhanh

if let error = error as NSError? {
  if error.domain == FunctionsErrorDomain {
    let code = FunctionsErrorCode(rawValue: error.code)
    let message = error.localizedDescription
    let details = error.userInfo[FunctionsErrorDetailsKey]
  }
  // ...
}

Objective-C

if (error) {
  if (error.domain == FIRFunctionsErrorDomain) {
    FIRFunctionsErrorCode code = error.code;
    NSString *message = error.localizedDescription;
    NSObject *details = error.userInfo[FIRFunctionsErrorDetailsKey];
  }
  // ...
}

Phiên bản web 8

var addMessage = firebase.functions().httpsCallable('addMessage');
addMessage({ text: messageText })
  .then((result) => {
    // Read result of the Cloud Function.
    var sanitizedMessage = result.data.text;
  })
  .catch((error) => {
    // Getting the Error details.
    var code = error.code;
    var message = error.message;
    var details = error.details;
    // ...
  });

Phiên bản web 9

import { getFunctions, httpsCallable } from "firebase/functions";

const functions = getFunctions();
const addMessage = httpsCallable(functions, 'addMessage');
addMessage({ text: messageText })
  .then((result) => {
    // Read result of the Cloud Function.
    /** @type {any} */
    const data = result.data;
    const sanitizedMessage = data.text;
  })
  .catch((error) => {
    // Getting the Error details.
    const code = error.code;
    const message = error.message;
    const details = error.details;
    // ...
  });

Java

addMessage(inputMessage)
        .addOnCompleteListener(new OnCompleteListener<String>() {
            @Override
            public void onComplete(@NonNull Task<String> task) {
                if (!task.isSuccessful()) {
                    Exception e = task.getException();
                    if (e instanceof FirebaseFunctionsException) {
                        FirebaseFunctionsException ffe = (FirebaseFunctionsException) e;
                        FirebaseFunctionsException.Code code = ffe.getCode();
                        Object details = ffe.getDetails();
                    }

                    // ...
                }

                // ...
            }
        });

Kotlin + KTX

addMessage(inputMessage)
        .addOnCompleteListener(OnCompleteListener { task ->
            if (!task.isSuccessful) {
                val e = task.exception
                if (e is FirebaseFunctionsException) {
                    val code = e.code
                    val details = e.details
                }

                // ...
            }

            // ...
        })

C ++

void OnAddMessageCallback(
    const firebase::Future<firebase::functions::HttpsCallableResult>& future) {
  if (future.error() != firebase::functions::kErrorNone) {
    // Function error code, will be kErrorInternal if the failure was not
    // handled properly in the function call.
    auto code = static_cast<firebase::functions::Error>(future.error());

    // Display the error in the UI.
    DisplayError(code, future.error_message());
    return;
  }

  const firebase::functions::HttpsCallableResult *result = future.result();
  firebase::Variant data = result->data();
  // This will assert if the result returned from the function wasn't a string.
  std::string message = data.string_value();
  // Display the result in the UI.
  DisplayResult(message);
}

// ...

// ...
  auto future = AddMessage(message);
  future.OnCompletion(OnAddMessageCallback);
// ...

Đoàn kết

 addMessage(text).ContinueWith((task) => {
  if (task.IsFaulted) {
    foreach (var inner in task.Exception.InnerExceptions) {
      if (inner is FunctionsException) {
        var e = (FunctionsException) inner;
        // Function error code, will be INTERNAL if the failure
        // was not handled properly in the function call.
        var code = e.ErrorCode;
        var message = e.ErrorMessage;
      }
    }
  } else {
    string result = task.Result;
  }
});

Trước khi bạn khởi động ứng dụng, bạn nên cho phép ứng dụng kiểm tra để giúp đảm bảo rằng chỉ các ứng dụng của bạn có thể truy cập vào thiết bị đầu cuối chức năng callable của bạn.