脚本仅在数组中打印最后一个文件,而不是所有文件
我正在阅读有关Flannagan 7ED的 javaScript《权威指南》的有关承诺的信息。在书中有一个脚本,该脚本显示了如何为任意数量的URL动态构建承诺链。脚本如下:
function fetchSequentially(urls) {
// We'll store the URL bodies here as we fetch them
const bodies = [];
// Here's a Promise-returning function that fetches one body
function fetchOne(url) {
return fetch(url)
.then(response => response.text())
.then(body => {
// We save the body to the array, and we're purposely
// omitting a return value here (returning undefined)
bodies.push(body);
});
}
// Start with a Promise that will fulfill right away (with value undefined)
let p = Promise.resolve(undefined);
// Now loop through the desired URLs, building a Promise chain
// of arbitrary length, fetching one URL at each stage of the chain
for (url of urls) {
p = p.then(() => fetchOne(url));
}
// When the last Promise in that chain is fulfilled, then the
// bodies array is ready. So let's return a Promise for that
// bodies array. Note that we don't include any error handlers:
// we want to allow errors to propagate to the caller.
return p.then(() => bodies);
}
//The script was run as below
//I added the line below to declare the urls array
let urls = ['/data.txt', '/readme.txt', '/textfile.txt'];
//the line below is from the book
fetchSequentially(urls)
.then(bodies => {
console.log(bodies)
})
.catch(e => console.error(e));
我添加了让URL
行以运行脚本以在我的PC上获取3个文本文件。
当脚本运行时,它似乎仅获取最后一个文件textfile.txt
,并且在控制台中3次打印出第三文件的内容。我以为脚本将检索所有3个文件的内容,将它们添加到身体数组中,然后将所有3个文件的内容记录到控制器上。
谁能发现为什么这不起作用?
I'm reading about Promises in JavaScript The Definitive Guide by Flannagan 7ed. In the book there is a script which shows how to build a Promise chain dynamically for an arbitrary number of URLs. The script is as follows:
function fetchSequentially(urls) {
// We'll store the URL bodies here as we fetch them
const bodies = [];
// Here's a Promise-returning function that fetches one body
function fetchOne(url) {
return fetch(url)
.then(response => response.text())
.then(body => {
// We save the body to the array, and we're purposely
// omitting a return value here (returning undefined)
bodies.push(body);
});
}
// Start with a Promise that will fulfill right away (with value undefined)
let p = Promise.resolve(undefined);
// Now loop through the desired URLs, building a Promise chain
// of arbitrary length, fetching one URL at each stage of the chain
for (url of urls) {
p = p.then(() => fetchOne(url));
}
// When the last Promise in that chain is fulfilled, then the
// bodies array is ready. So let's return a Promise for that
// bodies array. Note that we don't include any error handlers:
// we want to allow errors to propagate to the caller.
return p.then(() => bodies);
}
//The script was run as below
//I added the line below to declare the urls array
let urls = ['/data.txt', '/readme.txt', '/textfile.txt'];
//the line below is from the book
fetchSequentially(urls)
.then(bodies => {
console.log(bodies)
})
.catch(e => console.error(e));
I added the let urls
line to run the script to fetch 3 text files on my PC.
When the script runs it seems to only fetch the last file textfile.txt
, and it prints out the contents of the third file 3 times in the console. I thought the script would retrieve the contents of all 3 files, add them to the bodies array, and then log the contents of all 3 files to console.
Can anyone spot why this isn't working?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
看起来这是引起问题的部分:
在这里您正在创建一个全局变量
url
,并且由于它是异步运行的,fetchone(url)
正在使用最后一个实例它。相反,您可以做类似的事情:
这将为每次迭代创建
url
的本地实例。通过异步进行迭代的这种编程方式可以引入这样的微妙错误,因此我建议您明确地根据迭代创建新实例的样式。类似:
尽管有多个承诺的这种事情,您可能只想用
.map
使用Promise.all
:It looks like this is the section that's causing problems:
Here you're creating a global variable
url
, and since it's running asynchronously,fetchOne(url)
is using the last instance of it.Instead you can do something like:
This creates a local instance of
url
for each iteration.This sort of style of programming of iterating through arrays asynchronously can introduce subtle errors like this one, so I'd recommend a style that unambiguously creates a new instance per iteration. Something like:
Though for this sort of thing with multiple promises, you might just want to do a
.map
withPromise.all
: