我一直很好奇的一件事是:为什么要使用发电机来多填充异步/等待?
确保我可以考虑到它们在JavaScript中的工作方式,但是当有更好的选择时,为什么要使用该方法?
解决方案:只需写承诺
它尽可能简单。异步/等待的是句法糖的承诺链,所以为什么不将它们翻译成字面上:承诺链。
跟踪状态对象中的结果,即使在以后的延续功能中,您也可以访问它们。
唯一的缺点是您没有获得可变阴影,而是会得到可变的覆盖。但这可以通过使用Push'n'Pop机制使用类似堆栈的数据结构来琐碎地解决。
例子
让我演示我提出的替代方法,例如regenerator-runtime
:
简单的线性转换
async function fetchJson(url) {
const response = await fetch(url);
if (!response.ok) {
throw new Error("KO");
}
return response.json();
}
改变它应该给我们:
function fetchJson(url) {
return fetch(url).then(response => {
if (!response.ok) {
throw new Error("KO");
}
return response.json();
});
}
这几乎是逐条转换为简单的基于承诺的解决方案。
如果我们想制定转换制服,那么它可以给我们:
function fetchJson(url) {
const state = {};
return fetch(url).then(response => {
state.response = response;
if (!response.ok) {
throw new Error("KO");
}
return response.json();
});
}
需要以前的结果
async function stuff(input) {
const response = await api.put(input);
const extractedData = await extractData(response);
return {
response,
data: extractedData,
};
}
这应该变成:
function stuff(input) {
const state = {};
return api.put(input)
.then(response => {
state.response = response;
return extractData(response);
}).then(extractedData => {
state.extractedData = extractedData;
return {
response: state.response,
data: extractedData,
};
});
}
依赖范围的异常处理
async function stuff(input) {
const response = await api.put(input);
try {
const extractedData = await extractData(response);
return {
response,
data: extractedData,
};
} catch(e) {
throw new ApiError(e, response);
}
}
这应该变成:
function stuff(input) {
const state = {};
return api.put(input)
.then(response => {
state.response = response;
return extractData(response).then(extractedData => {
state.extractedData = extractedData;
return {
response,
data: extractedData,
};
}).catch(e => {
throw new ApiError(e, state.response);
});
});
}
您会注意到,只有在错误处理的情况下,我们实际上才需要筑巢。
最后
async function stuff(input) {
const response = await api.put(input);
try {
const extractedData = await extractData(response);
return {
response,
data: extractedData,
};
} catch(e) {
throw new ApiError(e, response);
} finally {
logStuff(response);
}
}
这应该变成:
function stuff(input) {
const state = {};
return api.put(input)
.then(response => {
state.response = response;
return extractData(response).then(extractedData => {
state.extractedData = extractedData;
return {
response,
data: extractedData,
};
}).catch(e => {
throw new ApiError(e, state.response);
}).finally(() => {
logStuff(state.response);
});
});
}
或,如果我们想避免使用Promise#finally
并依靠初始提出的API:
function stuff(input) {
const state = {};
return api.put(input)
.then(response => {
state.response = response;
const finallyFn = () => {
logStuff(state.response);
};
return extractData(response).then(extractedData => {
state.extractedData = extractedData;
return {
response,
data: extractedData,
};
}).catch(e => {
finallyFn();
throw new ApiError(e, state.response);
}).then(_$res => {
finallyFn();
return _$res;
});
});
}