Эта страница была переведа с помощью Cloud Translation API.
Switch to English

Вызов функций из вашего приложения

Облачные функции для клиентских SDK Firebase позволяют вызывать функции непосредственно из приложения Firebase. Чтобы вызвать функцию из вашего приложения таким образом, напишите и разверните функцию HTTPS Callable в облачных функциях, а затем добавьте клиентскую логику для вызова функции из вашего приложения.

Важно помнить, что вызываемые функции HTTPS похожи, но не идентичны функциям HTTP. Чтобы использовать вызываемые функции HTTPS, вы должны использовать клиентский SDK для своей платформы вместе с backend API functions.https (или реализовать протокол). Вызываемые объекты имеют следующие ключевые отличия от функций HTTP:

  • С вызываемыми объектами аутентификация Firebase и токены FCM, если они доступны, автоматически включаются в запросы.
  • Триггер functions.https.onCall автоматически десериализует тело запроса и проверяет токены аутентификации.

Firebase SDK для облачных функций v0.9.1 и выше взаимодействует с этими минимальными версиями клиентского SDK Firebase для поддержки вызываемых функций HTTPS:

  • Firebase SDK для iOS 6.33.0
  • Firebase SDK для Android 19.1.0
  • SDK Firebase для JavaScript 7.21.0

Если вы хотите добавить аналогичные функции в приложение, созданное на неподдерживаемой платформе, см. Спецификацию протокола для https.onCall . В оставшейся части этого руководства приведены инструкции по написанию, развертыванию и вызову вызываемой функции HTTPS для iOS, Android, Интернета, C ++ и Unity.

Напишите и разверните вызываемую функцию

Используйте functions.https.onCall чтобы создать функцию, вызываемую HTTPS. Этот метод принимает два параметра: data и необязательный context :

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

Например, для вызываемой функции, которая сохраняет текстовое сообщение в базе данных реального времени, data могут содержать текст сообщения, а параметры context представляют информацию об авторизации пользователя:

// 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;

Расстояние между местоположением вызываемой функции и местоположением вызывающего клиента может создавать задержку в сети. Чтобы оптимизировать производительность, подумайте об указании местоположения функции, где это применимо, и убедитесь, что вы выровняли местоположение вызываемого объекта с расположением, установленным при инициализации SDK на стороне клиента.

Отправка результата

Чтобы отправить данные обратно клиенту, верните данные, которые могут быть закодированы в JSON. Например, чтобы вернуть результат операции сложения:

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

Чтобы вернуть данные после асинхронной операции, верните обещание. Данные, возвращаемые обещанием, отправляются обратно клиенту. Например, вы можете вернуть очищенный текст, который вызываемая функция записала в базу данных реального времени:

// 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 };
})

Обработка ошибок

Чтобы клиент получал полезные сведения об ошибках, возвращайте ошибки из вызываемого объекта, бросая (или возвращая обещание, отклоненное с помощью) экземпляра functions.https.HttpsError . У ошибки есть атрибут code который может быть одним из значений, перечисленных в functions.https.HttpsError . У ошибок также есть строковое message , которое по умолчанию является пустой строкой. У них также может быть необязательное поле details с произвольным значением. Если из ваших функций HttpsError ошибка, HttpsError от HttpsError , ваш клиент вместо этого получает сообщение об ошибке INTERNAL и internal код.

Например, функция может выдавать ошибки проверки данных и аутентификации с сообщениями об ошибках, чтобы вернуться к вызывающему клиенту:

// 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.');
}

Разверните вызываемую функцию

После сохранения завершенной вызываемой функции в index.js она развертывается вместе со всеми другими функциями при запуске firebase deploy . Чтобы развернуть только вызываемый --only , используйте аргумент --only как показано, для частичного развертывания :

$ firebase deploy --only functions:addMessage

Если вы столкнулись с ошибками разрешений при развертывании функций, убедитесь, что соответствующие роли IAM назначены пользователю, выполняющему команды развертывания.

Настройте среду разработки клиента

Убедитесь, что вы соответствуете всем предварительным требованиям, а затем добавьте в приложение необходимые зависимости и клиентские библиотеки.

iOS

  1. Следуйте инструкциям, чтобы добавить Firebase в свое приложение iOS .
  2. Добавьте модуль Cloud Functions в свой Podfile :
    pod 'Firebase/Functions'
  3. Сохраните файл, затем запустите:
    pod install

Интернет

  1. Следуйте инструкциям, чтобы добавить Firebase в свое веб-приложение .
  2. Добавьте в приложение ядро ​​Firebase и клиентские библиотеки Cloud Functions:
    <script src="https://www.gstatic.com/firebasejs/7.21.0/firebase.js"></script>
    <script src="https://www.gstatic.com/firebasejs/7.21.0/firebase-functions.js"></script>
    

SDK Cloud Functions также доступен в виде пакета npm.

  1. Выполните следующую команду со своего терминала:
    npm install firebase@7.21.0 --save
    
  2. Требуется вручную как ядро ​​Firebase, так и облачные функции:
    const firebase = require("firebase");
    // Required for side-effects
    require("firebase/functions");
    

Ява

  1. Следуйте инструкциям, чтобы добавить Firebase в свое приложение для Android .
  2. В файле build.gradle уровня проекта обязательно build.gradle репозиторий Google Maven как в buildscript и в разделы allprojects .
  3. Добавьте зависимость для библиотеки Android Cloud Functions в файл Gradle вашего модуля (уровня приложения) (обычно app/build.gradle ):
    implementation 'com.google.firebase:firebase-functions:19.1.0'
    

Котлин + KTX

  1. Следуйте инструкциям, чтобы добавить Firebase в свое приложение для Android .
  2. В файле build.gradle уровня проекта обязательно build.gradle репозиторий Google Maven как в buildscript и в разделы allprojects .
  3. Добавьте зависимость для библиотеки Android Cloud Functions в файл Gradle вашего модуля (уровня приложения) (обычно app/build.gradle ):
    implementation 'com.google.firebase:firebase-functions:19.1.0'
    

C ++

Для C ++ с Android :

  1. Следуйте инструкциям, чтобы добавить Firebase в свой проект C ++ .
  2. В файле build.gradle уровня проекта обязательно build.gradle репозиторий Google Maven как в buildscript и в разделы allprojects .
  3. Добавьте firebase_functions библиотеку в свой CMakeLists.txt файл.

Для C ++ с iOS :

  1. Следуйте инструкциям, чтобы добавить Firebase в свой проект C ++ .
  2. Добавьте модуль Cloud Functions в свой Podfile :
    pod 'Firebase/Functions'
  3. Сохраните файл, затем запустите:
    pod install
  4. Добавьте ядро ​​Firebase и фреймворки Cloud Functions из Firebase C ++ SDK в свой проект Xcode.
    • firebase.framework
    • firebase_functions.framework

Единство

  1. Следуйте инструкциям, чтобы добавить Firebase в свой проект Unity .
  2. Добавьте FirebaseFunctions.unitypackage из Firebase Unity SDK в свой проект Unity.

Инициализировать клиентский SDK

Инициализировать экземпляр облачных функций:

Swift

lazy var functions = Functions.functions()

Цель-C

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

Интернет

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();

Ява

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

Котлин + KTX

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

C ++

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

Единство

functions = Firebase.Functions.DefaultInstance;

Вызов функции

Swift

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 text = (result?.data as? [String: Any])?["text"] as? String {
    self.resultField.text = text
  }
}

Цель-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"];
}];

Интернет

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

Ява

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;
                }
            });
}

Котлин + 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);
}

Единство

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;
  });
}

Обработка ошибок на клиенте

Клиент получает сообщение об ошибке, если сервер выдал ошибку или полученное обещание было отклонено.

Если ошибка, возвращаемая функцией, имеет тип function.https.HttpsError , то клиент получает code ошибки, message и details об ошибке сервера. В противном случае ошибка содержит сообщение INTERNAL и код INTERNAL . См. Руководство по обработке ошибок в вызываемой функции.

Swift

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]
  }
  // ...
}

Цель-C

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

Интернет

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

Ява

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();
                    }

                    // ...
                }

                // ...
            }
        });

Котлин + 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);
// ...

Единство

 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;
  }
});