HTTP POST请求在计划的云函数内部不起作用。

huangapple go评论85阅读模式
英文:

HTTP POST request inside scheduled Cloud Function is not working

问题

以下是我的调度程序,我从Firebase数据库中读取数据并通过调用receiptValidationRequest(key, receiptData, date)来更新数据。在这个函数内部,我尝试从苹果的HTTP调用响应中检索验证数据,但它不正常工作。有时它可以正常工作,一些数据得到更新。我不确定为什么会发生这种情况以及我漏掉了什么。

exports.updateDatabaseScheduler = functions.pubsub.schedule('0 0 */3 * *').onRun(async context => {
    console.log('scheduler started');
    await ref.on('value', function(snapshot) {
        snapshot.forEach(function(childSnapshot) {
            var childData = childSnapshot.val();
            console.log(i++ + " : " + childSnapshot.key);
            receiptValidationRequest(childSnapshot.key, childData['ReceiptData'], myDate);
        });
    });
    console.log('scheduler finished');
});

async function receiptValidationRequest(userID, receiptData, myDate){
    let password = 'my password';
    
    try{
        const data = JSON.stringify({
            'receipt-data': receiptData,
            'password' : password,
            'exclude-old-transactions': false
        });

        const options = {
            resolveWithFullResponse: true,
            hostname: 'buy.itunes.apple.com',
            port: 443,
            path: '/verifyReceipt',
            method: 'POST',
            json: true,
            headers: {
                'Content-Type': 'application/json',
            }
        };

        const req = await https.request(options,res => {
            myStatusCode[0] = res.statusCode;
            let expireDate = [];
            let transactionId = [];
            var trialPeriod = [];
            var body = '';

            console.log(`statusCode: ${res.statusCode}`);
            res.on('data', d => {
                body = body + d;
            });
            res.on("end", () => {
                body = JSON.parse(body);
                let array = Object.keys(body);

                console.log("body : "+body);
                //在这里解析数据
                insertIntoDB(userID, expireDate, transactionId, trialPeriod, myDate);
            });
        });
        req.write(data);
        req.end();
    }catch(e){
        req.on('error', (error) => {
            console.error(error)
        });
    }   
}

希望这对你有所帮助。如果需要进一步的解释或帮助,请随时告诉我。

英文:

Below is my scheduler where I am reading data from firebase database and updating data by calling receiptValidationRequest(key, receiptData, date) . Inside this function , I try to retrieve validation data from the response of HTTP call to apple, but its not working properly. Sometimes it works and a few data got updated. I am not sure why is this happening and what i am missing there.

exports.updateDatabaseScheduler = functions.pubsub.schedule('0 0 */3 * *').onRun(async context => {
console.log('scheduler started');
await ref.on('value', function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var childData = childSnapshot.val();
console.log(i++ + " : " +childSnapshot.key);
receiptValidationRequest(childSnapshot.key, childData['ReceiptData'], myDate);
});
});
console.log('scheduler finished');
});
async function receiptValidationRequest(userID, receiptData, myDate){
let password = 'my password';
try{
const data = JSON.stringify({
'receipt-data': receiptData,
'password' : password,
'exclude-old-transactions': false
});
const options = {
resolveWithFullResponse: true,
// hostname: 'sandbox.itunes.apple.com',
hostname: 'buy.itunes.apple.com',
port: 443,
path: '/verifyReceipt',
method: 'POST',
json: true,
headers: {
'Content-Type': 'application/json',
// 'Content-Length': data.length
}
};
const req =  await https.request(options,res => {
myStatusCode[0] = res.statusCode;
let expireDate = [];
let transactionId = [];
var trialPeriod = [];
var body = '';
console.log(`statusCode: ${res.statusCode}`);
res.on('data', d => {
body = body + d;
// console.log("body : "+body);
});
res.on("end", () => {
body = JSON.parse(body);
let array = Object.keys(body);
console.log("body : "+body);
//parsing data here
insertIntoDB(userID, expireDate, transactionId, trialPeriod, myDate);
});
});
req.write(data);
req.end();
}catch(e){
req.on('error', (error) => {
console.error(error)
});
}   
}

答案1

得分: 2

你需要返回一个承诺(Promise),在所有异步工作完成时解析。没有这个,Cloud Functions 不知道何时安全关闭函数。你现在有的是竞争条件 - 有时工作在 Cloud Functions 关闭之前完成,但并不总是如此。

我建议考虑使用另一个HTTP库,它更容易处理承诺,比如 "request-promise"。

英文:

You need to return a promise that resolves when all of the asynchronous work is complete. Without that, Cloud Functions doesn't know when it's safe to shut down the function. What you have right now is a race condition - sometimes the work compeltes before Cloud Functions shuts down, but not always.

I suggest looking into another HTTP library that makes it easier to deal with promises, such as "request-promise".

答案2

得分: 1

receiptValidationRequest 是一个异步函数。在调用它时,您没有等待。此外,使用 for..ofPromise.all 而不是 forEach,因为 forEach 在循环中无法处理 promises。

英文:

receiptValidationRequest is an async functioN. You are not awaiting while calling in forEach. Also, use for..of or promise.all instead of forEach as forEach doesn't work with promises in loop.

huangapple
  • 本文由 发表于 2020年1月6日 18:23:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/59610359.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定