我有一个Promise,它曾经等待接收完整的JSON字符串,但是现在它仅返回JSON字符串的一小部分。我目前正在使用Shopify API创建客户,这就是响应字符串应该是这样的:
def check_time_until_logout
@time_left = Devise.timeout_in.seconds - (Time.now.to_i - user_session["last_request_at"]).round
end
但是,这实际上是我要回来的:
{
"customer": {
"id": 1073339461,
"email": "steve.lastnameson@example.com",
"accepts_marketing": false,
"created_at": "2019-04-18T15:42:33-04:00",
"updated_at": "2019-04-18T15:42:33-04:00",
"first_name": "Steve",
"last_name": "Lastnameson",
"orders_count": 0,
"state": "disabled",
"total_spent": "0.00",
"last_order_id": null,
"note": null,
"verified_email": true,
"multipass_identifier": null,
"tax_exempt": false,
"phone": "+15142546011",
"tags": "",
"last_order_name": null,
"currency": "USD",
"addresses": [
{
"id": 1053317291,
"customer_id": 1073339461,
"first_name": "Mother",
"last_name": "Lastnameson",
"company": null,
"address1": "123 Oak St",
"address2": null,
"city": "Ottawa",
"province": "Ontario",
"country": "Canada",
"zip": "123 ABC",
"phone": "555-1212",
"name": "Mother Lastnameson",
"province_code": "ON",
"country_code": "CA",
"country_name": "Canada",
"default": true
}
],
"accepts_marketing_updated_at": "2019-04-18T15:42:33-04:00",
"marketing_opt_in_level": null,
"admin_graphql_api_id": "gid://shopify/Customer/1073339461",
"default_address": {
"id": 1053317291,
"customer_id": 1073339461,
"first_name": "Mother",
"last_name": "Lastnameson",
"company": null,
"address1": "123 Oak St",
"address2": null,
"city": "Ottawa",
"province": "Ontario",
"country": "Canada",
"zip": "123 ABC",
"phone": "555-1212",
"name": "Mother Lastnameson",
"province_code": "ON",
"country_code": "CA",
"country_name": "Canada",
"default": true
}
}
}
我所承诺的功能应该在继续执行之前等待结果,但是如您所见,由于某种原因,它严重切断了字符串。
自我首次编写该函数以来的过去6个月中,它一直没有出现问题。今天是它开始这样做的第一天。
以下是函数(AWS Lambda上的Node 8.10):
{"customer
这是我调用上面函数的函数:
async function makeCall(path, method, data = '', again = true) {
return new Promise((resolve, reject) => {
const bearer = "Basic " + Buffer.from(shopKey + ":" + shopPass).toString('base64');
const options = {
host: shopURL,
path: path,
method: method,
headers: {
"Content-Type" : "application/json",
"Authorization" : bearer
}
};
const req = http.request(options, (res) => {
});
req.on('response', function(res){
res.on('data', function(chunk){
const body = chunk.toString('utf8');
console.log('chunk', chunk);
console.log(body);
resolve(JSON.parse(body));
});
});
req.on('error', (e) => {
if (again){
setTimeout(makeCall(path, method, data, again = false), 3000);
} else {
reject(e.message);
}
});
// send the request
req.write(JSON.stringify(data));
req.end();
});
}
答案 0 :(得分:1)
我认为问题在于您进行分块的方式。请求可能会逐段向您发送数据,因此您需要将代码更改为:
async function makeCall(path, method, data = '', again = true) {
return new Promise((resolve, reject) => {
const bearer = "Basic " + Buffer.from(shopKey + ":" + shopPass).toString('base64');
const options = {
host: shopURL,
path: path,
method: method,
headers: {
"Content-Type" : "application/json",
"Authorization" : bearer
}
};
let body = '';
const req = http.request(options, (res) => {
// Here we are potentially getting chunks of data that we are
// adding to the main result "body"
res.on('data', function(chunk){
body += chunk;
});
// Once the request ends we can resolve with the result
res.on('end', function() {
resolve(JSON.parse(body));
});
});
req.on('error', (e) => {
if (again){
// Updated so that it forwards on the response/error,
// and only gets called after the timeout
setTimeout(() => makeCall(path, method, data, false).then(resolve).catch(reject), 3000);
} else {
reject(e.message);
}
});
// send the request
req.write(JSON.stringify(data));
req.end();
});
};