Учитывая, что вы не указываете, в каком контексте это находится, я сделаю несколько предположений:
- Я предполагаю, что
_data.read()
уже не поддерживает возврат обещания.
- Я предполагаю, что этот код должен либо вызывать функцию обратного вызова, либо возвращать обещание.
Мой (несколько наивный) подход к этому был бы:
- Карта
orderItems
в Обещания для каждой цены этого предмета.
- Отобразить результат в общую сумму
- Вернуть полученное обещание ИЛИ вызвать обратный вызов.
Вот аннотированный пример того, как вы можете это сделать:
// Promise.all takes an array of promises and returns
// a new promise that completes when all the promises in the array are complete.
const promiseOfPrices = Promise.all(
// Here we map all the items in the shopping cart into promises for each of their prices
userData.shoppingcart.map(
// The Promise object takes a single function that it will immediatly call with functions to resolve or
// reject the promise. I suggest reading up on Promises if you're not familiar with them.
itemName => new Promise((resolve, reject) => {
// Here, we have a `reject` and `resolve` function that will each complete the new promise,
// either in success or error respectfully.
// Do the actual read of your file or database or whatever
_data.read('menuitems', itemName, (err, itemData) => {
// If there was an error, reject this promise.
if (err) reject(err);
// Otherwise, we're successful and we resolve with the price of the item
else resolve(itemData.price);
});
})
)
);
// Now, we have a promise (promiseOfPrices) for all the prices of the items in the cart. We use `then` which will
// perform a transform on the result, much like the `map` function on an Array.
const promiseOfTotal = promiseOfPrices.then(
// Here we use the `Array.reduce` function to succinctly sum the values in the array.
arrayOfCartItemPrices => arrayOfCartItemPrices.reduce(
// For each item, reduce calls our function with the current sum and an item in the array. We produce a new
// sum by adding the sum to the item price.
(sum, itemPrice) => sum + itemPrice,
// This is the initial value for sum, 0.
0
)
);
Если вы можете вернуть обещание и просто хотите вернуть сумму, тогда
return promiseOfTotal;
Если у вас есть обратный вызов, который ожидает (ошибка, результат), то сделайте что-то вроде этого:
promiseOfTotal.then(
result => callback(null, result),
error => callback(error, null),
)
Если вам нужно больше работать с результатом, вы можете сделать это с другим, тогда:
promiseOfTotal.then(
priceSum => {
// Do work here
},
// Optionally handle errors here:
error => {
// Do error handling here.
}
)
Обратите внимание, что с помощью обещаний, функций стрелок и понимания массива (map
и reduce
) мы избегаем сложной и сложной для отслеживания мутации переменных и циклов. Это «функциональный» стиль программирования, и, хотя его труднее освоить, в целом он безопаснее и чище, чем альтернативы. Я предлагаю не торопиться, чтобы понять, как это работает, поскольку это поможет вам написать код, который с меньшей вероятностью будет иметь ошибки, когда вы имеете дело со сложными вещами, такими как асинхронность.
Наконец, я не запускал этот код. Это может иметь ошибку или два. Не стесняйтесь просить разъяснений или если это не работает.
Удачи!
P.S. Я не стал использовать async
/ await
, потому что я думаю, что это будет менее понятно, чем прямое использование Обещаний, а использование Promise.all
необходимо для параллелизма в любом случае. Здесь абсолютно возможно использовать их с хорошим эффектом, но я оставлю это как упражнение для ОП.