像这样在javascript中使用代码明智吗?
是的。你的代码没问题。
除了第二个请求之后,fetch(anotherUrl).then(function(response) {
,
我会用response.json().then(function(data2) {
替换return response.json();
- 就像第一个请求之后一样。
变量data2
将包含所需的内部URL请求的响应主体。
这意味着-无论你想用data2
做什么,你必须在这个第二个回调函数中完成(因为你没有返回一个promise)。
此外,更多的输出将有助于理解正在发生的事情。
1. 原始代码-稍作修改
在进行这些更改后,以下是包含你的代码的Stack Snippet:1
const url = 'https://jsonplaceholder.typicode.com/todos/1';
const anotherUrl = 'https://jsonplaceholder.typicode.com/todos/4';
fetch(url, {
method: 'get'
}).then(function (response) {
response.json().then(function (data) {
console.log('Response body of outer "url":');
console.log(JSON.stringify(data) + '\n\n');
fetch(anotherUrl).then(function (response) {
response.json().then(function (data2) {
console.log('Response body of inner "anotherUrl":');
console.log(JSON.stringify(data2) + '\n\n');
});
}).catch(function () {
console.log('Booo');
});
});
})
.catch(function (error) {
console.log('Request failed', error);
});
.as-console-wrapper { max-height: 100% !important; top: 0; }
这样也可以,不过现在更常见的是使用箭头函数来定义函数。
2. 重构后的代码
这是您代码的重构版本。
它有一个内部的链式/嵌套请求- fetch(urlInner)
- 依赖于从前一个/外部请求检索到的数据:fetch(urlOuter)
。
通过返回外部和内部URL获取的Promise,
可以在以后的代码中访问/解决承诺的结果:
2
const urlOuter = 'https://jsonplaceholder.typicode.com/todos/1';
let urlInner = '';
const resultPromise = fetch(urlOuter)
.then(responseO => responseO.json())
.then(responseBodyO => {
console.log('The response body of the outer request:');
console.log(JSON.stringify(responseBodyO) + '\n\n');
const neededValue = responseBodyO.id + 3;
urlInner = 'https://jsonplaceholder.typicode.com/todos/' + neededValue;
console.log('neededValue=' + neededValue + ', URL=' + urlInner);
return fetch(urlInner)
.then(responseI => responseI.json())
.then(responseBodyI => {
console.log('The response body of the inner/nested request:');
console.log(JSON.stringify(responseBodyI) + '\n\n');
return responseBodyI;
}).catch(err => {
console.error('Failed to fetch - ' + urlInner);
console.error(err);
});
}).catch(err => {
console.error('Failed to fetch - ' + urlOuter);
console.error(err);
});
resultPromise.then(jsonResult => {
console.log('Result - the title is "' + jsonResult.title + '".');
});
.as-console-wrapper { max-height: 100% !important; top: 0; }
请注意,缩进不超过八个空格。
3. 这种代码风格的优点
显然,这是一种嵌套式的编写代码的方式——意味着链接请求
fetch(urlInner)
被缩进并在第一个请求
fetch(urlOuter)
的回调函数中完成。然而,缩进树是合理的,并且这种风格与我的关于链接请求的直觉相吻合。但更重要的是,这种风格使得编写能够准确定位哪个URL失败的错误消息成为可能。
运行下面的片段,看看错误消息如何指出是“内部/第二个URL”导致了错误:
const urlOuter = 'https://jsonplaceholder.typicode.com/todos/1';
let urlInner = '';
const resultPromise = fetch(urlOuter)
.then(responseO => responseO.json())
.then(responseBodyO => {
console.log('The response body of the outer request:');
console.log(JSON.stringify(responseBodyO) + '\n\n');
const neededValue = responseBodyO.id + 3;
urlInner = 'https://VERY-BAD-URL.typicode.com/todos/' + neededValue;
console.log('neededValue=' + neededValue + ', URL=' + urlInner);
return fetch(urlInner)
.then(responseI => responseI.json())
.then(responseBodyI => {
console.log('The response body of the inner/nested request:');
console.log(JSON.stringify(responseBodyI) + '\n\n');
return responseBodyI;
}).catch(err => {
console.error('Failed to fetch - ' + urlInner);
console.error(err);
});
}).catch(err => {
console.error('Failed to fetch - ' + urlOuter);
console.error(err);
});
resultPromise.then(jsonResult => {
console.log('Result - the title is "' + jsonResult.title + '".');
});
.as-console-wrapper { max-height: 100% !important; top: 0; }
4. 将所有的.then()
展开?
受他人启发,你可能会想将所有的.then()
展开成下面这样。
我建议不要这样做,或者至少在这样做之前三思。为什么?
- 如果没有错误,这样做并没有什么影响。
- 如果出现错误,则这种风格将强制较少的不同错误消息:
const urlOuter = 'https://jsonplaceholder.typicode.com/todos/1';
let urlInner = '';
const resultPromise = fetch(urlOuter)
.then(responseO => responseO.json())
.then(responseBodyO => {
console.log('The response body of the outer request:');
console.log(JSON.stringify(responseBodyO) + '\n\n');
const neededValue = responseBodyO.id + 3;
urlInner = 'https://VERY-BAD-URL.typicode.com/todos/' + neededValue;
console.log('neededValue=' + neededValue + ', URL=' + urlInner);
return fetch(urlInner);
})
.then(responseI => responseI.json())
.then(responseBodyI => {
console.log('The response body of the inner/nested request:');
console.log(JSON.stringify(responseBodyI) + '\n\n');
return responseBodyI;
}).catch(err => {
console.error('Failed to fetch one or more of these URLs:');
console.log(urlOuter);
console.log(urlInner);
console.log(err);
});
.as-console-wrapper { max-height: 100% !important; top: 0; }
代码结构很简洁,但最后捕获的错误无法确定是哪个URL请求失败了。
1 本答案的所有代码块都符合JavaScript Semistandard Style。
2 关于第11行的代码 return fetch(urlInner)
,很容易忘记加上 return
。我曾经在写完这个答案后也忘了加上它。如果你确实忘了加上它,resultPromise
将不会包含任何 promise。代码块的最后三行将无法执行,输出结果将为空。整个结果将会失败!
.then()
链接调用。 - guest271314then
)回调中return
,那么你的最终.catch()
就无法工作。 - Bergi