js如何从异步的fetch函数包装成一个过程,return请求的结果HTM(gethtm)
在 JavaScript 中,fetch
是一个异步操作,要将其包装成一个能返回请求结果的函数,你可以使用 async/await
语法或者返回一个 Promise
对象。下面分别为你介绍这两种实现方式:
方法一:使用 async/await
语法
async/await
是 ES2017 引入的语法糖,它可以让异步代码看起来更像同步代码,便于处理异步操作的结果。
javascript
async function gethtm(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
return data;
} catch (error) {
console.error('Fetch error:', error);
return null;
}
}
// 调用示例
async function main() {
const url = 'https://example.com/api';
const result = await gethtm(url);
console.log('最终结果:', result);
}
main();
代码解释
- 定义
gethtm
函数:使用async
关键字将gethtm
函数标记为异步函数。 - 发送
fetch
请求:使用await
关键字等待fetch
请求完成,并将响应结果赋值给response
。 - 检查响应状态:如果响应状态不正常,抛出错误。
- 解析响应数据:使用
await
关键字等待response.json()
方法完成,并将解析后的数据赋值给data
。 - 返回结果:将解析后的数据返回。
- 错误处理:使用
try...catch
块捕获可能出现的错误,并在控制台输出错误信息。 - 调用
gethtm
函数:在main
函数中调用gethtm
函数,并使用await
关键字等待结果返回。
方法二:返回一个 Promise
对象
如果你不想使用 async/await
语法,也可以直接返回一个 Promise
对象。
javascript
function gethtm(url) {
return fetch(url)
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => {
return data;
})
.catch(error => {
console.error('Fetch error:', error);
return null;
});
}
// 调用示例
const url = 'https://example.com/api';
gethtm(url).then(result => {
console.log('最终结果:', result);
});
代码解释
- 定义
gethtm
函数:在函数内部直接返回一个fetch
请求的Promise
对象。 - 处理响应结果:使用
.then()
方法处理fetch
请求的响应结果,并在.then()
方法中返回解析后的数据。 - 错误处理:使用
.catch()
方法捕获可能出现的错误,并在控制台输出错误信息。 - 调用
gethtm
函数:调用gethtm
函数,并使用.then()
方法处理返回的结果。
这两种方法都可以将异步的 fetch
函数包装成一个能返回请求结果的函数,你可以根据自己的喜好选择合适的方法。
采用AWAIT,会不会让进程卡住?如果同时调用10次gethtm,是同时请求,还是等一个完成再下一个?
1. await
是否会让进程卡住
在 JavaScript 中,await
本身不会让整个进程卡住,它只会阻塞当前的 async
函数的执行流程。JavaScript 是单线程的,但是它的运行环境(如浏览器或 Node.js)提供了异步操作的能力。await
用于等待一个 Promise
对象的解决(resolved)或拒绝(rejected),在等待期间,JavaScript 引擎可以去处理其他任务,例如处理用户交互、执行其他脚本等。
例如下面的代码
javascript
async function gethtm(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
return data;
} catch (error) {
console.error('Fetch error:', error);
return null;
}
}
async function main() {
console.log('开始执行');
const result = await gethtm('https://example.com');
console.log('请求完成,结果是', result);
console.log('继续执行其他任务');
}
main();
console.log('在等待请求时可以执行其他代码');
在这个例子中,当执行到 await gethtm('https://example.com')
时,main
函数会暂停执行,等待 gethtm
函数返回结果,但此时 JavaScript 引擎可以继续执行 main
函数外部的代码,比如 console.log('在等待请求时可以执行其他代码')
。
2. 同时调用 10 次 gethtm
的执行情况
如果直接在 async
函数里依次使用 await
调用 10 次 gethtm
,那么请求会依次进行,即等一个完成后再开始下一个。示例如下:
javascript
async function main() {
const urls = [
'https://example1.com',
'https://example2.com',
// 其他 8 个 URL
];
for (const url of urls) {
const result = await gethtm(url);
console.log('请求结果:', result);
}
}
main();
在这个循环中,每次调用 gethtm
后都会使用 await
等待该请求完成,所以下一个请求要等到前一个请求结束后才会发起。
若想让这 10 个请求同时发起,可以使用 Promise.all
方法。Promise.all
接收一个 Promise
数组,它会并行执行这些 Promise
,并在所有 Promise
都解决后返回一个包含所有结果的数组。示例如下:
javascript
async function main() {
const urls = [
'https://example1.com',
'https://example2.com',
// 其他 8 个 URL
];
const promises = urls.map(url => gethtm(url));
const results = await Promise.all(promises);
console.log('所有请求结果:', results);
}
main();
在这个例子中,urls.map(url => gethtm(url))
会创建一个包含 10 个 Promise
的数组,每个 Promise
代表一个 gethtm
请求。然后使用 Promise.all
并行执行这些请求,并使用 await
等待所有请求完成。这样,这 10 个请求会同时发起,而不是依次进行。