3 javascript ecmascript-6 es6-promise fetch-api es6-class
假设我有以下数据spanish.json:
[
{"word": "casa", "translation": "house"},
{"word": "coche", "translation": "car"},
{"word": "calle", "translation": "street"}
]
Run Code Online (Sandbox Code Playgroud)
我有一个Dictionary类来加载它并添加一个搜索方法:
// Dictionary.js
class Dictionary {
constructor(url){
this.url = url;
this.entries = []; // we’ll fill this with a dictionary
this.initialize();
}
initialize(){
fetch(this.url)
.then(response => response.json())
.then(entries => this.entries = entries)
}
find(query){
return this.entries.filter(entry =>
entry.word == query)[0].translation
}
}
Run Code Online (Sandbox Code Playgroud)
我可以实例化它,并使用它通过这个小单页应用程序来查找“ calle”:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>spanish dictionary</title>
</head>
<body>
<p><input placeholder="Search for a Spanish word" type="">
<p><output></output>
<script src=Dictionary.js></script>
<script>
let es2en = new Dictionary('spanish.json')
console.log(es2en.find('calle')) // 'street'
input.addEventListener('submit', ev => {
ev.preventDefault();
let translation = dictionary.find(ev.target.value);
output.innerHTML = translation;
})
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
到目前为止,一切都很好。但是,假设我要子类化,Dictionary
并添加一个对所有单词进行计数并将其添加到页面的方法。(伙计,我需要一些投资者。)
因此,我获得了另一轮资金并实施CountingDictionary:
class CountingDictionary extends Dictionary {
constructor(url){
super(url)
}
countEntries(){
return this.entries.length
}
}
Run Code Online (Sandbox Code Playgroud)
新的单页应用程序:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Counting Spanish Dictionary</title>
</head>
<body>
<p><input placeholder="Search for a Spanish word" type="">
<p><output></output>
<script src=Dictionary.js></script>
<script>
let
es2en = new CountingDictionary('spanish.json'),
h1 = document.querySelector('h1'),
input = document.querySelector('input'),
output = document.querySelector('output');
h1.innerHTML = es2en.countEntries();
input.addEventListener('input', ev => {
ev.preventDefault();
let translation = es2en.find(ev.target.value);
if(translation)
output.innerHTML = `${translation}`;
})
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
加载此页面时,h1将填充0。
我知道我的问题是什么,我只是不知道如何解决。
问题在于该fetch调用返回一个Promise,并且.entries仅在Promise 返回后,该属性中才会填充来自URL的数据。在此之前,
.entries保持为空。
如何.countEntries等待获取承诺解决?
还是有一种更好的方法可以完全实现我在这里想要的?
问题在于该
fetch调用返回一个Promise,并且.entries仅在Promise 返回后,该属性中才会填充来自URL的数据。在此之前,.entries保持为空。
您需要做出entries承诺。这样,您的所有方法都必须返回Promise,但是Dictionary实例立即可用。
class Dictionary {
constructor(url) {
this.entriesPromise = fetch(url)
.then(response => response.json())
}
find(query) {
return this.entriesPromise.then(entries => {
var entry = entries.find(e => e.word == query);
return entry && entry.translation;
});
}
}
class CountingDictionary extends Dictionary {
countEntries() {
return this.entriesPromise.then(entries => entries.length);
}
}
Run Code Online (Sandbox Code Playgroud)
let es2en = new CountingDictionary('spanish.json'),
h1 = document.querySelector('h1'),
input = document.querySelector('input'),
output = document.querySelector('output');
es2en.countEntries().then(len => {
fh1.innerHTML = len;
});
input.addEventListener(ev => {
ev.preventDefault();
es2en.find(ev.target.value).then(translation => {
if (translation)
output.innerHTML = translation;
});
});
Run Code Online (Sandbox Code Playgroud)
还是有一种更好的方法可以完全实现我在这里想要的?
class Dictionary {
constructor(entries) {
this.entries = entries;
}
static load(url) {
return fetch(url)
.then(response => response.json())
.then(entries => new this(entries));
}
find(query) {
var entry = this.entries.find(e => e.word == query);
return entry && entry.translation;
}
}
class CountingDictionary extends Dictionary {
countEntries() {
return this.entries.length;
}
}
Run Code Online (Sandbox Code Playgroud)
let es2enPromise = CountingDictionary.load('spanish.json'),
h1 = document.querySelector('h1'),
input = document.querySelector('input'),
output = document.querySelector('output');
es2enPromise.then(es2en => {
fh1.innerHTML = es2en.countEntries();
input.addEventListener(…);
});
Run Code Online (Sandbox Code Playgroud)
如您所见,与包含Promise的实例相比,此方案需要较少的整体嵌套。同样,该实例的Promise可以更好地组合,例如,当您需要在安装侦听器并显示输出之前等待domready时,您将能够获得DOM的Promise,并且可以同时使用Promise.all。
| 归档时间: |
|
| 查看次数: |
1982 次 |
| 最近记录: |