Javascript 如何优化这段代码,因为它是异步的
如您所见,对_data.read的调用是异步的,因为我是从文件中读取的 但是我需要等待读取所有文件,这样我才能计算出总价。这就是为什么我放置该条件[++I==userData.shoppingcart.length] 一般来说,我对javascript和nodejs都是新手,从来都不是一个很好的程序员,但无论如何,我的观点是,我确信这不是一个好的方法,如果两个文件同时读取,然后该条件从未运行过,或者totalPrice的计算做得很糟糕,会怎么样 有人能给我一些指导吗?Javascript 如何优化这段代码,因为它是异步的,javascript,node.js,asynchronous,conditional,Javascript,Node.js,Asynchronous,Conditional,如您所见,对_data.read的调用是异步的,因为我是从文件中读取的 但是我需要等待读取所有文件,这样我才能计算出总价。这就是为什么我放置该条件[++I==userData.shoppingcart.length] 一般来说,我对javascript和nodejs都是新手,从来都不是一个很好的程序员,但无论如何,我的观点是,我确信这不是一个好的方法,如果两个文件同时读取,然后该条件从未运行过,或者totalPrice的计算做得很糟糕,会怎么样 有人能给我一些指导吗? 提前谢谢你 这就是如何使用
提前谢谢你 这就是如何使用promises(Flavor)按顺序阅读项目:
本例假设
\u data.read
支持异步/await
。但是,如果没有,它可以使用nodejs模块中的promisify
函数“promisified”鉴于您没有指定这是在什么上下文中,我将做一些假设:
\u data.read()
不支持返回承诺orderItems
映射为该商品每个价格的承诺var orderItems = userData.shoppingcart;
let totalPrice = 0;
for (let itemName of userData.shoppingcart) {
const itemData = await _data.read('menuitems', itemName);
totalPrice += itemData.price;
}
如果你能回报一个承诺,而你只想回报总数,那么
// 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
)
);
如果您有一个预期(err,result)的回调,则执行以下操作:
return promiseOfTotal;
如果您需要对结果做更多的工作,您可以使用另一个来完成,然后:
promiseOfTotal.then(
result => callback(null, result),
error => callback(error, null),
)
注意,通过使用承诺、箭头函数和数组理解(map
和reduce
),我们避免了变量和循环的复杂和难以跟踪的变异。这是一种“函数式”编程风格,虽然学习起来有些困难,但通常比其他编程方式更安全、更干净。我建议您花点时间来理解它是如何工作的,因为它可以帮助您编写代码,在处理异步等复杂问题时,代码不太可能出现错误
最后,我还没有运行这段代码。它很可能有一两个bug。如果不起作用,请随时要求澄清
祝你好运
另外,我没有使用
async
/await
,因为我认为这比直接使用承诺和使用Promise要不清楚。无论如何,并行性都需要所有的。在这里完全可以使用它们来获得良好的效果,但我将把它作为练习留给OP.“如果同时读取两个文件会怎么样”-这不正是您想要的吗?基本上,是的,这就是想法-计算完成了多少任务,然后继续。不过也有很多陷阱,比如正确地考虑错误或者0次迭代的边缘情况(比如在空输入上),因此您最好使用一些经过验证的现有代码,而不是重新发明轮子。了解承诺和Promise.all
。是的,它们都可以同时读取,但我希望流量只有在所有内容都已读取后才能继续,因此我有正确和准确的totalPrice变量量。是的,我听说过Promise,但不知道如何使用它,我会对此进行一些搜索,谢谢@BergiYeah,这是按顺序运行的,而不是并行运行的,这可能是不可取的。我对async
/await
最大的一个问题是,它似乎鼓励减少并行代码。@bergi是的,在这种情况下,async/await
会将其添加到答案中。@YonaAppletree我发现,优化可读性而不是性能是可取的。@Christian当然。但是有表现,有表现。在本例中,您将获取可能是O(1)的内容并将其转换为O(N)。这与使用理解时创建的中间数组不同。O(1)对O(N)是巨大的,特别是当存在网络或文件读取或其他情况时。这至少值得仔细考虑。嗨@YonaAppletree非常感谢你的详细回答,从未使用过承诺,现在是学习它们的好时机!我相信我理解了你的逻辑,大体上理解了你的代码。我刚问了一个问题,承诺价格将是所有价格的数组,对吗?在这种情况下,如果有一个拒绝,我会知道,因为数组“promiseOfPrices”的长度将不同于我预期的长度,对吗?为了澄清,我现在接受你的详细回答:)@TiagoM承诺是一个非常好的抽象概念,我建议你阅读这些文件,因为我在一篇文章中所能说的不止这些。回答您的问题:否。Promise.all
生成一个新的承诺,当传递给它的所有承诺都解决(成功)或拒绝其中任何一个时,它将解决(失败)。因此,promiseOfPrices
将是一个承诺,通过一系列的价格来解决。它永远不会使用不同长度的数组进行解析。如果任何一个都失败了,promiseOfPrices
promiseOfPrices将以第一个错误拒绝(失败)。谷歌关于承诺的介绍性教程看起来相当不错:换句话说,如果你想知道是否出了问题,看看我给出的关于做更多工作的示例,其中有两个参数是。然后()
或者您可以使用.catch()
捕捉错误。您好@YonaAppletree只是想路过这里,感谢您提供的文档和解释!我终于让它按照我需要的方式工作了,使用了promissions.All-and-Then子句,我还将阅读您发送给我的文档,因为它听起来非常有文档记录!再次感谢您的帮助和宝贵时间!祝你一切顺利;)
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.
}
)