使用 async/await 重写 "rethrow"
下面你可以看到 “rethrow” 的例子。让我们来用 async/await
重写它,而不是使用 .then/catch
。
同时,我们可以在 demoGithubUser
中使用循环以摆脱递归:在 async/await
的帮助下很容易实现。
class HttpError extends Error {
constructor(response) {
super(`${response.status} for ${response.url}`);
this.name = 'HttpError';
this.response = response;
}
}
function loadJson(url) {
return fetch(url)
.then(response => {
if (response.status == 200) {
return response.json();
} else {
throw new HttpError(response);
}
});
}
// 询问用户名,直到 github 返回一个合法的用户
function demoGithubUser() {
let name = prompt("Enter a name?", "iliakan");
return loadJson(`https://api.github.com/users/${name}`)
.then(user => {
alert(`Full name: ${user.name}.`);
return user;
})
.catch(err => {
if (err instanceof HttpError && err.response.status == 404) {
alert("No such user, please reenter.");
return demoGithubUser();
} else {
throw err;
}
});
}
demoGithubUser();
这里没有什么技巧。只需要将 demoGithubUser
中的 .catch
替换为 try...catch
,然后在需要的地方加上 async/await
即可:
class HttpError extends Error {
constructor(response) {
super(`${response.status} for ${response.url}`);
this.name = 'HttpError';
this.response = response;
}
}
async function loadJson(url) {
let response = await fetch(url);
if (response.status == 200) {
return response.json();
} else {
throw new HttpError(response);
}
}
// 询问用户名,直到 github 返回一个合法的用户
async function demoGithubUser() {
let user;
while(true) {
let name = prompt("Enter a name?", "iliakan");
try {
user = await loadJson(`https://api.github.com/users/${name}`);
break; // 没有 error,退出循环
} catch(err) {
if (err instanceof HttpError && err.response.status == 404) {
// 循环将在 alert 后继续
alert("No such user, please reenter.");
} else {
// 未知的 error,再次抛出(rethrow)
throw err;
}
}
}
alert(`Full name: ${user.name}.`);
return user;
}
demoGithubUser();