为什么我在将数据写入云 Firestore 时收到无效参数错误?

Why am I getting an Invalid argument error when writing data to cloud firestore?

我正在尝试使用云函数将数据写入云 Firestore,但无论我做什么,我都会收到一条错误消息,指出这是一个错误的请求,并且它是一个无效的参数。我试过更改 data.text,因为我唯一的想法是这不是正确的调用。我一直在关注 Net Ninja 的教程,但在他的教程中他只处理一个领域。

云函数

exports.addHack = functions.https.onCall((data, context) => {
    admin.firestore().collection('Data').add({
        name: data.text,
        gender: data.text,
        age: data.text,
        email: data.text,
        address: data.text,
        number: data.text
    })
});

Javascript
它被包装在一个函数中,因为在用户按下提交之前我让它检查一些东西然后它执行这个函数但是看起来工作正常。

function submitHack() {
    const formContainer = document.querySelector('#formContainer');
    const addHack = firebase.functions().httpsCallable('addHack');
    addHack({
        name: document.getElementById("nameField").value,
        gender: document.getElementById("genderField").value,
        age: document.getElementById("ageField").value,
        email: document.getElementById("emailField").value,
        address: document.getElementById("addressField").value,
        number: document.getElementById("phoneField").value
    })
    .then(() => {
        formContainer.reset();
        alert('Submission Successful! Enjoy your visit!')
    })
    .catch(error => {
        alert(error.message);
    }) 
}

HTML
这是包含我要写入数据库的所有输入的表单,包括按钮

    <section>
      <h1>Registration</h1>
      <div id="formContainer">
        <div class="item">
          <label>Full Name:</label><br>
          <input type="text" id="nameField" placeholder="Enter Full Name">
        </div>
        <div class="item">
          <label>Gender:</label><br>
          <select id="genderField">
            <option value="null" selected>Please Select...</option>
            <option value="male">Male</option>
            <option value="female">Female</option>
            <option value="other">Other</option>
          </select>
        </div>
        <div class="item">
          <label>Age:</label><br>
          <input type="number" id="ageField">
        </div>
        <div class="item">
          <label>Email Address:</label><br>
          <input type="text" id="emailField" placeholder="Enter Email Address">
        </div>
        <div class="item">
          <label>Home Address:</label><br>
          <textarea type="text" id="addressField" placeholder="Enter Home Address"></textarea>
        </div>
        <div class="item">
          <label>Phone Number:</label><br>
          <input type="text" id="phoneField" placeholder="Enter Phone Number">
        </div>
        <div class="item">
          <input type="checkbox" id="checkbox">
          <label>I accept the <a id="termsLink" href="https://imgur.com/5lXi3Lc" target="_blank">Terms and Conditions</a></label>
        </div>
        <button class="call" id="submit">Submit</button>
      </div>

错误信息

{"error":{"message":"Bad Request","status":"INVALID_ARGUMENT"}}

如下调用Callable Cloud Function时

addHack({
        name: document.getElementById("nameField").value,
        gender: document.getElementById("genderField").value,
        ...
    })

您正在传递一个具有多个属性的对象。

所以,在Cloud Function中,你需要使用这些属性,如下:

exports.addHack = functions.https.onCall((data, context) => {
   
        const name = data.name;
        const gender = data.gender;        

        // ...
});

此外,由于是Callable Cloud Function执行异步操作(Firestoreadd()方法),所以需要return一个Promise。 promise 编辑的数据 return 被发送回客户端。

所以下面应该可以解决问题(未经测试):

exports.addHack = functions.https.onCall((data, context) => {
   
        const name = data.name;
        const gender = data.gender;        

        // ...

        return admin.firestore().collection('Data').add({
           name,
           gender,
           // ...
       
        })
        .then(() => {
            return {result: "success"}
        })
        .catch(error => {
            //  See https://firebase.google.com/docs/functions/callable#handle_errors
        });

});

当然你也可以这样做:

exports.addHack = functions.https.onCall((data, context) => {

        return admin.firestore().collection('Data').add({
           name: data.name,
           gender: data.gender,
           // ...
        })
        .then(() => {
            return {result: "success"}
        })
        .catch(error => {
            //  See https://firebase.google.com/docs/functions/callable#handle_errors
        });

});

最后请注意,您似乎没有从按钮调用 submitHack() 函数。我建议您首先使用一些常量测试 Cloud Function,例如通过做:

const addHack = firebase.functions().httpsCallable('addHack');
addHack({
    name: "test name",
    gender: "testGender",
    age: ... ,
    // ...
})

当您确定它可以工作时,在表单和 Cloud Function 调用之间进行“连接”。