NodeJS Firebase函数需要在Firestore中编写脚本

k5ifujac  于 2023-10-17  发布在  Node.js
关注(0)|答案(1)|浏览(131)

我正在构建一个移动的应用程序,在某些操作(如userCreate)上,我触发一些Firebase函数来执行对第三个服务的API调用,然后在Firestore数据库中写入一些内容。
理论上一切都可以工作,但在实践中,API调用非常快(即使是冷启动场景),但数据库写入可能需要几个小时才能完成(如果他们这样做,我怀疑有时会花费太长时间并超时)。
由于API调用工作得很好,DB在某些情况下也写得很好,我怀疑这仅仅是由于我对JavaScript的管理非常糟糕,因为我对JS一无所知。
这里有两个与此问题有关的示例函数,只是为了说明当我在Create或HTTPS上触发函数时会发生这种情况。

onCreate函数

const functions = require("firebase-functions");
const axios = require('axios')

// The Firebase Admin SDK to access the Firestore.
const admin = require('firebase-admin');
admin.initializeApp();

// Third party service credentials generation during onCreate request
exports.

buildCredentials = functions.auth.user().onCreate((user) => {

// Request to Third party to generate an Client Access Token
axios({
    method: "post",
    url: "https://api.ThirdParty.com/api/v1/oauth/token",
    data: "client_id=xxx&client_secret=yyy&grant_type=client_credentials&scope=all:all",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
  })
    .then(function (response) {
      //handle success
      console.log('new user created: ')
      console.log(user.id);
      console.log(response.data);
    
      // We write a new document in the users collection with the user ID and the Client Access Token
      const db = admin.firestore();
      const newUser = {
        uid: user.uid,
        clientAccessToken: response.data.access_token
      };

      db.collection('users').doc(user.uid).set(newUser)
      .catch(function (error) {
      //handle error
      console.log(error);
    });

    })
    .catch(function (response) {
      //handle error
      console.log(response);
    });
})

HTTPS onCall函数

exports.paymentRequest = functions.https.onCall(async (data, context) => {
    const clientAccessToken = data.clientAccessToken;
    const recipientIban = data.recipientIban;
    const recipientName = data.recipientName;
    const paymentDescription = data.paymentDescription;
    const paymentReference = data.paymentReference;
    const productPrice = parseInt(data.productPrice);
    const uid = data.uid;

    const jsonData = {
        "destinations": [
                {
                    "accountNumber": recipientIban,
                    "type": "iban"          
                }
            ],
            "amount": productPrice,
            "currency": "EUR",
            "market": "FR",
            "recipientName": recipientName,
            "sourceMessage": paymentDescription,
            "remittanceInformation": {
                "type": "UNSTRUCTURED",
                "value": paymentReference
                },
            "paymentScheme": "SEPA_INSTANT_CREDIT_TRANSFER"
    };
    (async function(){
    response = await axios({
        method: "post",
        url: "https://api.ThirdParty.com/api/v1/pay",
        headers: { 
            'Content-Type': 'application/json',
            Accept: 'application/json',
            Authorization: `Bearer ${clientAccessToken}`,},
        data: jsonData,
        })

        // We write a the payment request ID in the user's document
        const db = admin.firestore();
        const paymentRequestID = response.data.id;

        db.collection('users').doc(uid).set({
            paymentRequestID: paymentRequestID
        }, { merge: true })
        .catch(function (error) {
            //handle error
            console.log(error);
            });
        console.log(response.data)
        return response.data
    })()
})

我是否认为这是一个可持续发展问题?或者是Firebase/Firestore问题?
谢谢

dbf7pr2w

dbf7pr2w1#

您没有返回异步方法(axios()set())返回的promise,这可能会导致Cloud Function的一些“不稳定”行为。
正如您将在官方Firebase video series的三个关于“JavaScript Promises”的视频中看到的那样,您必须在后台触发的Cloud Function中返回一个Promise或一个值,以向平台表示它已经完成,并避免它在异步操作完成之前被终止或在工作完成后继续运行。
以下调整应该可以做到这一点(未经测试):

onCreate函数:

buildCredentials = functions.auth.user().onCreate((user) => {

    // Request to Third party to generate an Client Access Token
    return axios({
        method: "post",
        url: "https://api.ThirdParty.com/api/v1/oauth/token",
        data: "client_id=xxx&client_secret=yyy&grant_type=client_credentials&scope=all:all",
        headers: { "Content-Type": "application/x-www-form-urlencoded" },
      })
        .then(function (response) {
          //handle success
          console.log('new user created: ')
          console.log(user.id);
          console.log(response.data);
        
          // We write a new document in the users collection with the user ID and the Client Access Token
          const db = admin.firestore();
          const newUser = {
            uid: user.uid,
            clientAccessToken: response.data.access_token
          };
    
          return db.collection('users').doc(user.uid).set(newUser)
    
        })
        .catch(function (response) {
          //handle error
          console.log(response);
          return null;
        });
    })

可调用函数:

exports.paymentRequest = functions.https.onCall(async (data, context) => {
    
    try {
        
        const clientAccessToken = data.clientAccessToken;
        const recipientIban = data.recipientIban;
        const recipientName = data.recipientName;
        const paymentDescription = data.paymentDescription;
        const paymentReference = data.paymentReference;
        const productPrice = parseInt(data.productPrice);
        const uid = data.uid;
    
        const jsonData = {
            // ...
        };
        const response = await axios({
            method: "post",
            url: "https://api.ThirdParty.com/api/v1/pay",
            headers: {
                'Content-Type': 'application/json',
                Accept: 'application/json',
                Authorization: `Bearer ${clientAccessToken}`,
            },
            data: jsonData,
        })
    
        // We write a the payment request ID in the user's document
        const db = admin.firestore();
        const paymentRequestID = response.data.id;
    
        await db.collection('users').doc(uid).set({
            paymentRequestID: paymentRequestID
        }, { merge: true })
            
        console.log(response.data)
        return response.data
        
    } catch (error) {
        
        // See https://firebase.google.com/docs/functions/callable#handle_errors    
    
    }
    
})

相关问题