在node.js应用程序中,我试图从API查找产品列表,然后仅获取第一项的缩略图。
在我的代码中,getOrderDetails是一个promise,然后,如果它是第一个产品,它将调用函数getImage,这也是一个promise。
但是,当我运行代码时,orderDetails会被填充而不会显示缩略图-因此,看起来代码没有等待getImage函数解析。
请有人能解释我做错了吗?
提前谢谢!
if (siteConfig.storeIntegration == 'Cart') {
getOrderDetails(restPathOrder)
.then(function(res) {
var orderDetails = '';
for (i = 0; i < res.items.length; i++) {
productId = res.items[i]['productId'];
thumbnail = '';
if (i == 0) {
getImage(productId, restApiKey)
.then(function(res) {
thumbnail = res;
console.log('thumbnail:' + res);
})
}
orderDetails = orderDetails + res.items[i]['quantity'] + ',' + res.items[i]['name'] + ',' + productUrl + ',' + thumbnail;
}
console.log(orderDetails);
})
}
function getOrderDetails(restPath) {
return new Promise((resolve, reject) => {
request(restPath, function (error, response, body) {
if (!error && response.statusCode == 200) {
restData = JSON.parse(body);
resolve(restData)
}
})
})
}
function getImage(productId, restApiKey) {
return new Promise((resolve, reject) => {
var restPathProduct = storeURL + restApiKey + productId;
request(restPathProduct, function (error, response, body) {
if (!error && response.statusCode == 200) {
restData = JSON.parse(body);
thumbnail = restData.image[0];
resolve(thumbnail);
}
})
})
}
答案 0 :(得分:1)
我建议使用新的await
语法吗?
async main() {
if (siteConfig.storeIntegration == 'Cart') {
let res = await getOrderDetails(restPathOrder);
var orderDetails = '';
for (i = 0; i < res.items.length; i++) {
productId = res.items[i]['productId'];
let thumbnail = '';
if (i == 0) {
thumbnail = await getImage(productId, restApiKey);
}
orderDetails += res.items[i]['quantity'] + ',' + res.items[i]['name'] + ',' + productUrl + ',' + thumbnail;
}
console.log(orderDetails);
}
}
答案 1 :(得分:1)
@FrankerZ是正确的,异步/等待使代码更简洁。
我不确定productUrl来自何处的业务逻辑。
解决方案是将整个代码块包装在一个promise中,获取第一个订单的图片,然后在getImage的then
中处理订单的详细信息。
这是我的尝试,但有一些小的重构。希望它可以引导您朝正确的方向发展。
function process() {
// Wrap everything inside a promise, we then resolve with the order details
// Resolve is what gets returned in the .then((resolvedData)), reject is what gets returned in the .catch((rejectedThings))
return new Promise((resolve, reject) => {
// Get the order details
getOrderDetails(restPathOrder)
.then(function(orderRes) {
// Handle no items
if (!orderRes.items || orderRes.items.length === 0) {
return reject("No items") // You can deal with this in the catch
}
// Get first item
const firstOrder = orderRes.items[0];
// Fetch the first thumbnail then proceed to fetch the rest of the order details.
getImage(firstOrder.productId, restApiKey)
.then(function(thumbnail) {
let orderDetails = '';
// Build order details body
// N.B I'm not sure how you want orderDetails to appear, personally I would use a map instead of a forEach.
orderRes.items.forEach((item) => {
orderDetails = orderDetails + item.quantity + ',' + item.name + ',' + productUrl + ',' + thumbnail;
})
// Then resolve with the order details
return resolve(orderDetails);
})
})
})
}
// You can then call process as a promise with the order details
process().then(function(orderDetails) => console.log(orderDetails))