Облачная функция Firebase (асинхронная) не возвращает результат - PullRequest
1 голос
/ 10 апреля 2019

Я довольно плохо знаком с функциями Firebase / Firestore / Cloud и пробовал небольшой проект, в котором клиентское приложение вызывает функцию Firebase Cloud, чтобы сгенерировать несколько случайных ключей (случайных чисел), добавить их в Firestore и, при успешной записи, вернутьэти ключи к клиентскому приложению.Вроде как генератор случайных чисел.

Функция корректно вызывается клиентом (согласно Firebase Console), генерирует ключи, проверяет, существуют ли они в Firestore, и, если нет, добавляет их.Все работает до той части, где он должен вернуть результат клиенту.Здесь клиент никогда не получает результат (массив ключей).На самом деле обратный вызов в клиентском приложении (iOS / Swift) никогда не вызывается.

Я подозреваю, что проблема заключается в возвращаемом обещании?Согласно документации Firebase здесь, асинхронные вызовы должны возвращать Promise, хотя я не совсем уверен, что я делаю правильно https://firebase.google.com/docs/functions/callable

Вот код для облачной функции:

export const generateRandomKeys = functions.https.onCall(async (data, context) => {

  // Read data passed from client
  const numberOfKeys = data.numberOfKeys
  console.log("Number of keys to generate: ", numberOfKeys)

  // Generate some keys
  const generatedKeys = KeyMaker.newKeys(numberOfKeys)

  try {

    const randomkeys = []

    // Write keys to DB
    for (const key of generatedKeys) {
      const addedKey = await writeKeyToDB(key)
      randomkeys.push(addedKey)
    }

    return Promise.resolve(JSON.stringify(randomkeys))

  } catch (error) {
      console.log("Error has occured: ", error)
      throw new Error("An Error has occured: " + error)
  }
})


async function writeKeyToDB(key: string){

  try {
    // Check if a document with the same key already exists in the DB
    const docRef = db.collection("randomKeys").doc(key)
    const doc =  await docRef.get()

    // Document with same key found!
    if (doc.exists) {
      // Generate a new key and try again
      const newKey = KeyMaker.newKey()

      console.log("Will generate a new key and try again!. New key: ", newKey)
      await writeKeyToDB(newKey)
    }

    const keyDoc = {
      somefield: somevalue,     
    }

    // Write to DB then return result
    await docRef.set(keyDoc)

    return Promise.resolve(key)

  } catch (error) {
      return Promise.reject(error)
  }
}

Клиент (Swift)

     public static func generateNewRandomNumbers(numberOfKeys: Int) {

        FirebaseApp.configure()

        let functions = Functions.functions(region: FIRESTORE_REGION)

        functions.httpsCallable("generateRandomKeys").call(["numberOfKeys": numberOfKeys]) { (result, error) in

            // Nothing here executes                                                    
            print("----------got reply---------")
            if let error = error as NSError? {
                if error.domain == FunctionsErrorDomain {
                    let code = FunctionsErrorCode(rawValue: error.code)
                    let message = error.localizedDescription
                    print("Error \(String(describing: code)): " + message)
                }
            }

            if let keys = (result?.data as? [String]) {
                dump(keys)
            }
        }
    }

Ответы [ 2 ]

1 голос
/ 10 апреля 2019

Не объединяйте Async/Await и Promise.Async функционирует как само возвращение Promise.

Сначала измените возврат вашей облачной функции на:

return JSON.stringify(randomkeys);

Также в writeKeyToDb измените возврат на:

return key;

и catch часть на:

throw Error(error);

Я также вижу проблему в том, что в облачной функции вы вызываете вашу writeKeyToDb функцию с 2 параметрами, но эта функция имеет только один.Но этот код, вероятно, находится в процессе

0 голосов
/ 11 апреля 2019

Наконец-то нашел проблему, спасибо Дагу и Доминику за то, что они направили меня в правильном направлении. Я удалил обещания и вернул непосредственно значения, но что более важно, мне не нужно было преобразовывать массив в JSON. Я наткнулся на HTTPSCallableResult документация

Я просто изменил это

return JSON.stringify(randomkeys);

до

return randomkeys

и на клиенте вместо

if let keys = (result?.data as? [String]) { dump(keys) }

Я делаю

if let keys = (result?.data as? NSArray) { dump(keys) }

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...