嗨,我有一个异步问题,当我试图过滤有声帧阵列时,它是空的,我需要在过滤器之前进行获取,我该怎么做?p>
const media = 'audio';
const searchInput = document.querySelector('.search');
const output = document.querySelector('.output')
searchInput.addEventListener('change', searchData);
async function searchData() {
let search = this.value;
const finalData = await getData(search);
render(finalData);
}
function render(data) {
let html;
if(media == 'image') {
html = data.map(result => {
return `
<div class="image">
<img src="${result.links[0].href}"/>
</div>
`
}).join("");
} else {
const audioFiles = [];
data.map(result => {
fetch(result.href)
.then(blob => blob.json())
.then(data => audioFiles.push(...data));
})
console.log(audioFiles);
/* filter .mp3? */
const regex = new RegExp(".mp3$");
const files = audioFiles.filter(file => {
return file.match(regex);
})
console.log(files);
}
output.innerHTML = html;
}
function getData(search) {
const endpoint = `https://images-api.nasa.gov/search?q=${search}&media_type=${media}`;
return fetch(endpoint)
.then(blob => blob.json())
.then(data => data.collection.items);
}
<input type="text" class="search" placeholder="planet">
<div class="output"></div>
音频文件在过滤器之前为空文件,我该如何修复它,以便在对其进行过滤器之前在那里?
看起来您可以将更多的 .then()
s链接到您现有的。
问题是:
data.map(result => {
fetch(result.href)
.then(blob => blob.json())
.then(data => audioFiles.push(...data));
})
// This part below is executing before `audiofiles` is populated
console.log(audioFiles);
/* filter .mp3? */
const regex = new RegExp(".mp3$");
const files = audioFiles.filter(file => {
return file.match(regex);
})
console.log(files);
尝试:
data.map(result => {
fetch(result.href)
.then(blob => blob.json())
.then(data => audioFiles.push(...data))
.then(() => new RegExp(".mp3$"))
.then((regex) => audioFiles.filter(file => file.match(regex)))
.then((files) => {
console.log(files)
// Set the HTML once it is done getting the audio
output.innerHTML = html
})
})
我们正在使用implicit returns
。
这个:
runFunction().then(data => console.log(data))
与:
相同runFunction().then(data => {
return console.log(data)
})
如果函数仅返回一个表达式,甚至 .then(data => data += 5)
。
执行原始代码时,您必须考虑JavaScript在做什么。首先,它开始获取返回承诺的音频文件,因此立即将其放入function queue
,然后继续执行代码。它首先执行console.log(audiofiles)
,但是函数队列中的获取尚未推入audiofiles
,因为2 ms以前,该承诺链开始执行blob.json()
。然后,它继续通过您的代码,并创建new RegExp
并同步设置files
的值,因为.filter()
是同步的。然后,它执行console.log(files)
,其中包含一些垃圾,因为音频文件可能会或可能没有将数据推入其中。合理地,在大多数情况下,还没有任何价值。
解决方案是强制代码等待,并且您已经使用了一些异步/等待语法,因此您也可以在这里使用它...
这也许是一个更好的解决方案,也更容易阅读,扩展和维护:
} else {
data.map(result => fetch(result.href))
.then(async (blob) => {
const data = await blob.json();
const audiofiles = [...data];
console.log(audioFiles);
/* filter .mp3? */
const regex = new RegExp(".mp3$");
const files = audioFiles.filter(file => file.match(regex));
console.log(files);
output.innerHTML = html;
})
}
我将您的代码解释好,好像您想最后加载HTML一样,但是根据适当的异步行为,如果页面尽快加载,并且在准备就绪时加载音频文件是最佳的。这可能是您最初的意图,在这种情况下,将其移回if/else
块外。
您应该等待从获取中的sonss fut滤波,我希望渲染函数也可以是异步
const media = 'audio';
const searchInput = document.querySelector('.search');
const output = document.querySelector('.output')
searchInput.addEventListener('change', searchData);
async function searchData() {
let search = this.value;
const finalData = await getData(search);
render(finalData);
}
async function render(data) {
let html;
if(media == 'image') {
html = data.map(result => {
return `
<div class="image">
<img src="${result.links[0].href}"/>
</div>
`
}).join("");
} else {
const regex = new RegExp(".mp3$");
const files = await Promise.all(data.map(async result => {
const response = await fetch(result.href)
const blob = await blob.json()
return blob.filter(file => file.match(regex));
}))
console.log(files);
}
output.innerHTML = html;
}
function getData(search) {
const endpoint = `https://images-api.nasa.gov/search?q=${search}&media_type=${media}`;
return fetch(endpoint)
.then(blob => blob.json())
.then(data => data.collection.items);
}
<input type="text" class="search" placeholder="planet">
<div class="output"></div>