整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

JavaScript - Fetch API 完全手册

果您想从 API 加载数据,那么 fetch API 是在 JavaScript 中执行此操作的最佳方式。您不需要引入任何第三方库,就可以直接使用方便的fetch。

像上图所示,绝大多数浏览器已经原生支持Fetch,所以您可以放心使用。Node.js 对它的支持也正在路上,Fetch 已经作为 Node v17 中的实验性功能提供,你可以使用 node app.js --experimental-fetch 来开启它。

Fetch API 的基本使用

Fetch API 是基于Promise的,所以如果你不了解Promise, 最好先学习一下Promise。

调用 fetch API 的最简单方法是将 URL 传递给 fetch 函数。

这将返回一个包含响应数据的Promise。此响应数据包含状态属性以及将原始响应数据转换为 JSON、文本或其他格式的方法。

上面显示res.json() 是在我们的响应中调用 json() 方法,这个方法会返回另外一个 promise,该 promise 从我们的响应中解析 JSON 数据。

我们可以在后面的then方法中获取到最终需要的JSON数据对象。

如果您从 JSON api 获取数据,这就是大多数获取请求的样子。 我们首先获取 URL,然后将响应转换为 JSON,最后使用最终 .then 中的数据。

如果使用async/await语法,可能会更简单点。

Fetch 参数

这将涵盖您的一些 fetch 用途,但通常您需要传递其他选项来进行 fetch 配置。 fetch 函数采用第二个选项对象参数,其中包含大量潜在选项。

method

最常用的选项是方法选项。 此选项允许您设置要使用的 HTTP 动词(GET、POST、PUT、DELETE 等)。

body

如果您正在修改方法,那么您可能需要将数据与您的请求一起传递。 这就是 body 选项的用武之地。body 不接受对象,因此如果您想将 JSON 传递给您的 API,您必须首先将其转换为字符串。

headers

现在,执行上述操作可能看起来像是将 JSON 传递给 API 所需要做的一切,但这实际上是行不通的。 原因是您需要设置正确的标头来告诉您的 API 您正在发送 JSON 信息。 此标头选项允许您设置所需的任何 HTTP 标头。

上面这组代码是将 JSON 传递给 API 所需要做的一切。

signal

最后一个要说的的是信号选项。 这个选项接受一个 AbortSignal,它可以用来中止一个获取请求。

正如您从代码中看到的那样,这比其他选项要复杂一些。 首先你必须创建一个新的 AbortController 这个控制器有一个信号属性,这是你传递给signal选项的。 控制器还有一个 abort 方法,当调用该方法时,将使用相关信号中止获取请求。 这将导致 fetch Promise以 AbortError Reject异常。

这些选项应该是可以cover你90%左右的用例。具体还有其他一些不常用的可以去查看官网文档。

总结:

fetch API 是一个功能强大的工具,易于上手,它包含适用于每个可以想象的用例的许多高级选项。最重要的是,马上node.js就可以原生支持它,逻辑可以前后端共享,岂不美哉!

感谢阅读!

文介绍HTML5 <audio>音频元素的属性,方法,以及事件相关的API的基本使用。

内容有些多,完整阅读需要点时间,但很实用,可以先马后看。

一、audio使用基本案例

<audio controls>
 <source src="audiofile.mp3" type="audio/mpeg">
 <source src="audiofile.ogg" type="audio/ogg">
 <!-- 如果浏览器不支持,则会呈现下面内容 -->
 <p>你的浏览器不支持HTML5音频,你可以<a href="audiofile.mp3">下载</a>这个音频文件。</p>
</audio>

上面做法是早些年HTML5 <audio>常用代码,因为那时候IE8还是大头,各大浏览器对各类音频格式支持情况参差不齐,因此,才借助<source>元素同时引用多个不同格式的音频文件,通过type属性指定mime type避免重复加载情况出现。

但是,如今已经不需要这么麻烦了。我们直接下面这样就可以了:

<audio src="audiofile.mp3" controls></audio>

音频文件常见下面3种格式,.ogg, .wav和.mp3,其中,.ogg Safari浏览器不支持(目前版本13),IE到Edge16都不支持;.wav则是IE-IE11不支持;但是.mp3 IE9+都支持。因此,我们如果不想麻烦,直接一个MP3格式就好了,由于就一种文件格式,因此type属性也可以不用设置。

//zxx: 也可以使用MP4视频文件,因为MP4视频也包含ACC编码音频,不过就是体积大了很多,不建议这么使用。

<audio>元素IE9浏览器就开始支持,现在00后都快20岁了,也不需要为低版本浏览器做降级适配了。因此,简简单单一个<audio>元素就可以了。

二、Audio HTML属性

下面看下<audio>元素属性相关的一些细节。

autoplay

<audio src="audiofile.mp3" autoplay></audio>

autoplay是个布尔属性值,表示声音是否自动播放,默认不自动播放。然而,随着浏览器的发展,这个属性变得限制越来越多。首先在移动端,autoplay自动播放已经被禁止了,PC端也已经禁止,18年的时候,Chrome这么做了,然后被很多开发者抗议,后来又恢复autoplay(给大家缓冲时间),现在已经Chrome又不支持自动播放了。

原因是网页在没有警告的情况下自发地发出声音,可能会让用户不愉快,体验不太好。因此,浏览器通常只允许在特定情况下成功地进行自动播放。

关于更深入的autoplay策略可以参见MDN上的这篇文档。

不过根据我自己的一些实践,资源静音或者视频没有声音情况下,autoplay偶尔也是会执行的,不过都是偶现,触发自动播放原因不详。

loop

<audio src="audiofile.mp3" loop></audio>

loop是个布尔属性值,表示声音是否循环播放,默认不循环播放。loop属性适合用在可以不断循环的bgm背景音乐上。loop属性在各个平台,各个浏览器下的表现良好,大家可以放心使用。

JS设置音频循环播放可以:

document.querySelector('audio').loop = true;

muted

示意:

<audio src="audiofile.mp3" muted></audio>

muted也是个布尔属性值,表示音频是否静音,默认不静音播放。muted属性在各个平台,各个浏览器下的表现良好,大家可以放心使用。

JS设置音频静音可以:

document.querySelector('audio').muted = true;

preload

示意:

<audio src="audiofile.mp3" preload="auto"></audio>

preload可以指定音频的预加载策略,也就是在播放之前需要提前加载好音频的哪些资源。支持下面3个属性值:

  1. none:表示在点击播放按钮之前不加载任何信息。
  2. metadata: 下载音频的meta信息,就是视频长度,类型,还有作者(如果有)等信息。/li>
  3. auto: 会尝试下载整个音频,如今5G都快来了,流量已经不值钱了,因此,我个人是更推荐使用auto的,体验更好一点。然后,通常浏览器自己也会优化加载策略,不会所有音频文件都加载下来,只是会加载一部分,保证点击播放按钮的时候,可以立即播放。

preload属性在iOS Safari浏览器下是被禁止的(桌面端无此问题),对于一些对音频播放时间实际要求比较高的场合,会给我们开发带来困难。通常解决方法是,第一次触摸的时候,音频静音,同时触发音频play()然后很快再pause(),此时,可以有类似preload的预加载行为。

不过,Safari以后可能会改变preload在移动端的加载策略,因为越往后流量越不值钱,这种自以为是的优化反而会成为一种桎梏。

controls

示意:

<audio src="audiofile.mp3" controls></audio>

controls是个布尔属性值,表示声音是否显示音频播放暂停等控制器,默认是不显示的。

如果没有设置controls属性,整个音频文件播放面板都是完全隐藏的;如果有设置,则UI可能类似下面这张图(Chrome PC,设置了静音)。


不同浏览器,以及不同版本浏览器,其UI都不一样。如果是开发to用户侧产品,需要自定义音频播放器的UI,让各个浏览器下长相一致,大家可以去github上找找开源的项目。

src

示意:

<audio src="audiofile.mp3"></audio>

src属性表示音频的文件地址。可以用在<audio>元素上,也可以用在<source>元素上。<audio>元素上只能一个音频地址,使用<source>可以并列多个不同格式的音频文件。

type

<audio src="audiofile.mp3" type="audio/mpeg"></audio>

type属性用来指定音频文件的mime type类型。虽然不加type类型,浏览器也能正确播放音频文件,但通常建议加上type属性。当然,如果src音频格式不固定,则type属性反而推荐不加,错误的type不如没有type。

三、在JS中调用的audio属性

<audio>元素还有一些属性只能通过JavaScript设置,假设有HTML如下:

<audio id="myAudio" src="audiofile.mp3"></audio>

则:

currentTime

currentTime是一个可读兼可写的属性,用来设置或获取当前已经播放的时长,单位是秒。

例如:

// 获取音频已经播放时长
var playedTime = myAudio.currentTime;

如果音频尚未开始播放,则playedTime的返回值是0。

我们也可以通过设置currentTime属性值,让我们的音频定位到我们希望的时间点进行播放,例如,从5秒那里开始播放,则:

// 跳到5秒那里
myAudio.currentTime = 5;

volume

volume也是一个可读兼可写的属性,用来设置或获取音频的音量大小,范围是0-1。

例如,设置音量50%,则:

// 设置音量50%
myAudio.volume = 0.5;

如果音频文件设置了muted为true,则myAudio.volume的返回值是0。

playbackRate

playbackRate是一个可读兼可写的属性,用来设置或获取当前媒体文件的播放速率,值为数值,例如:

// 获取音频播放速率
var audioSpeed = audio.playbackRate;
// 设置音频设置播放速率为正常速度的1.5倍
audio.playbackRate = 1.5;

速率范围

根据文档显示,Gecko内核浏览器速率范围是0.25到5.0,超出这个范围就静音。

对于Chrome浏览器,我自己实地测试了下,速率上限居然可以到16,如下图:


然后,此属性兼容性不错,IE9+都支持。

paused

paused是一个只读属性,表示当前音频是否处于暂停状态。

// true或false
console.log(myAudio.paused);

未播放或者播放暂停都会返回true。

四、播放与暂停等JS方法

play()

音频播放示意,没有额外参数:

myAudio.play();

需要注意的是,目前在现代浏览器下,无论是桌面端还是移动端,执行myAudio.play()不总是有效果的。

目前策略是,web网页需要至少又一次可信任的用户行为后,才能myAudio.play()播放才可以执行,否则会报错。


可信任的用户行为包括touchstart触摸或者click点击。

pause()

音频暂停示意,没有额外参数:

myAudio.pause();

音频元素是没有stop()方法的,如果你想要实现音频的stop()效果,可以先设置currentTime属性值为0,然后在执行pause()方法。

canPlayType()

canPlayType()可以用来检测浏览器是否支持某种类型的音频文件,支持一个mime type值作为参数。使用示意:

if (myAudio.canPlayType('audio/mpeg')) {
 // 如果支持mp3
 // 这里搞事情
}

canPlayType()方法可以返回下面三个值中的某一个:

  1. probably
  2. maybe
  3. ""(空字符串)

实际开发的时候,只要不是空字符串,我们都可以认为是支持的,因此,直接使用if弱匹配返回值即可,例如:

var myAudio = document.createElement('audio');
if (myAudio.canPlayType('audio/mpeg')) {
 myAudio.setAttribute('src','audiofile.mp3');
}
if (myAudio.canPlayType('audio/ogg')) {
 myAudio.setAttribute('src','audiofile.ogg');
}

load()

触发音频文件的加载。如果浏览器不支持preload属性,则此方法也不会有效果。

此方法没有额外参数:

myAudio.load();

五、音频媒体加载事件

下面讲讲关于音频加载及相关处理,根据我实际项目中的实践,这类加载事件在移动端,尤其iOS Safari并不总能触发,因为preload以及autoplay等属性的限制。

loadstart

loadstart事件简单地告诉我们加载过程已经开始,浏览器正在连接到媒体。

myAudio.addEventListener("loadstart", function() {
 // 抓取文件
});

durationchange

如果你想尽快知道音频文件的播放时长,则durationchange事件非常管用,因为音频文件默认duration初始值是NaN,当准确时长返回时候,会触发durationchange,此时我们就可以快速显示音频播放时间了。

通常实际开发,我们会使用00:00占位,durationchange事件触发后在替换为准确的总播放时间。

myAudio.addEventListener("durationchange", function() {
 // 可以显示播放时长了哟
});

loadedmetadata

当第一个音频文件字节数据到达时,会触发loadeddata事件。虽然播放头已经就位,但还没有准备好播放。

myAudio.addEventListener("loadeddata", function() {
 // 可以显示播放头
});

progress

progress事件在媒体文件仍然在下载中的时候触发,通常各种loading效果的显示就是在这个事件中。

myAudio.addEventListener("progress", function() {
 // 你可以让用户知道媒体文件正在下载
});

canplay

当媒体文件可以播放的时候会触发canplay事件。

我们在自定义音频播放器的时候,可以默认把一些按钮disabled禁用,等可以播放的时候再恢复为enabled,此时就可以使用canplay事件。

myAudio.addEventListener("canplay", function() {
 // 音频可以播放了
});

canplaythrough

canplaythrough事件在音频文件可以从头播放到尾时候触发。这种情况包括音频文件已经从头到尾加载完毕了,或者浏览器认为一定可以按时下载,不会发生缓冲停止。

myAudio.addEventListener("canplaythrough", function() {
 // 音频可以不发生缓冲从头播放到结束
});

音频事件触发的顺序

媒体事件加载顺序如下:

loadstart → durationchange → loadedmetadata → loadeddata → progress → canplay → canplaythrough

加载中断事件

还有一些事件实在媒体加载过程出现某种中断时将触发。

suspend

即使文件尚未完全下载,也不再拉取媒体数据。

abort

不是因为出错而导致的媒体数据下载中止。

error

媒体下载过程中错误。例如突然无网络了。或者文件地址不对。

emptied

媒体缓冲区已被清空,可能是由于错误或调用了load()方法重新加载。

stalled

媒体数据意外地不再可用。

六、音频媒体播放事件

下面介绍一些与媒体文件播放状态相关的一些事件。

timeupdate

每次currentTime属性值发生变化的时候会触发timeupdate事件。

实际开发的时候,这个事件每250毫秒出发一次。这个事件可用来实时显示播放进度。

myAudio.addEventListener("timeupdate", function() {
 // 更新与播放进度相关的内容
});

playing

音频文件在缺少媒体信息(如时长等)的时候,播放会被迫停止,如果之后在启动播放,会触发playing事件。

waiting

音频文件因为缺少媒体信息(如时长等)导致播放停止时会触发waiting事件。

play

play事件在play()方法生效,或者autoplay导致播放开始时候触发,此事件触发的播放状态一定是一个从暂停到播放。

pause

pause事件在pause()方法执行并生效后触发,此事件触发需要一个从播放到暂停的状态变化。

ended

当整个音频文件播放完毕的时候触发ended事件。

myAudio.addEventListener("ended", function() {
 // 当音轨播放完毕时候做你想做的事情
});

volumechange

音量发生变化的时候会触发volumechange事件,包括静音行为。

ratechange

播放速率发生变化的时候会触发ratechange事件。

七、缓冲相关的属性和方法

媒体文件的播放进度我们可以使用currentTime和duration属性获取,但是有时候,我们希望知道缓冲加载的进度,此时可以使用下面几个和缓冲相关属性和方法。

buffered

此属性让我们知道音频的哪些部分已被缓冲(提前下载)。它返回一个称为TimeRanges的对象。

myBufferedTimeRanges = myAudio.buffered;

seekable

seekable属性通知您是否可以直接跳到媒体的该部分,而不需要进一步缓冲。

mySeekableTimeRanges = myAudio.seekable;

Buffering相关事件

seeking

当媒体资源正在请求是会触发seeking事件。

seeked

当seeking属性变成false时候会触发seeked事件。

有关缓冲以及TimeRanges更深入具体的知识,可以参见这篇MDN文档。

八、结语与参考文档

本文展示的这些<audio>音频元素相关的属性和方法以及各种回调事件,对于<video>视频元素同样受用,基本上都是一模一样的,很多自动播放以及媒体自动加载策略也是一致的。

本文展示的这些API并不是全部,如果发现有遗漏,欢迎大家补充。

载说明:原创不易,未经授权,谢绝任何形式的转载

Midjourney 创作,未来API

大家好,随着技术的迅速发展,开发者们拥有了越来越多的令人惊叹的新工具和API。但是,我们发现在100多个API中,只有5%的API被开发者们积极地使用。

下面让我们来看看一些有用的Web API,它们可以帮助你将你的网站推向未来的巅峰!

1、屏幕捕获API

屏幕捕获API,正如其名,允许你捕获屏幕内容,让制作屏幕录像变得轻而易举。你需要一个视频元素来显示捕获的屏幕。点击开始按钮即可开始屏幕捕获。

<video id="preview" autoplay>
  Your browser doesn't support HTML5.
</video>
<button id="start" class="btn">Start</button>
// 获取HTML元素
const previewElem = document.getElementById("preview"); // 预览元素
const startBtn = document.getElementById("start"); // 开始按钮元素

// 异步函数,开始录制屏幕和声音
async function startRecording() {
  previewElem.srcObject = // 将预览元素的srcObject属性设置为获取到的屏幕和声音媒体流
    await navigator.mediaDevices.getDisplayMedia({
      video: true, // 录制视频
      audio: true, // 录制声音
    });
}

// 为开始按钮添加点击事件监听器,点击时调用startRecording函数
startBtn.addEventListener("click", startRecording);

2、Web Share API

Web Share API 允许你从一个网页分享文本、链接甚至是文件到设备上安装的其他应用程序。

// 异步函数,处理分享事件
async function shareHandler() {
  // 调用navigator.share方法进行分享,传入分享内容的相关信息
  navigator.share({
    title: "Tapajyoti Bose | Portfolio", // 分享标题
    text: "Check out my website", // 分享文本
    url: "https://tapajyoti-bose.vercel.app/", // 分享链接
  });
}

// 给某个元素添加点击事件监听器,点击时调用shareHandler函数
someElement.addEventListener("click", shareHandler);

注意:要使用 Web Share API,你需要从用户那里获得互动,例如按钮点击或触摸事件。

3、Intersection Observer API

Intersection Observer API 允许你检测元素何时进入或离开视口。这对于实现无限滚动非常有用。

简单的例子

// 创建一个IntersectionObserver实例,观察特定元素
const observer = new IntersectionObserver((entries) => {
  // 遍历每个entry,判断是否在视口内
  entries.forEach((entry) => {
    if (entry.isIntersecting) {
      // 元素进入视口,执行相应操作
    } else {
      // 元素离开视口,执行相应操作
    }
  });
});

// 将需要观察的元素传递给IntersectionObserver实例
const target = document.querySelector(".target");
observer.observe(target);

一个复杂的分页滚动(React版本)

<div id="root"></div>
/* The entire styling is totally optional */

* {
  font-family: Roboto;
}

body {
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.item {
  width: 80vw;
  margin: 12px 0;
  padding: 32px;
  border-radius: 8px;
  font-size: larger;
}

.loader {
  border: 8px solid #cccccc;
  border-top: 8px solid #3498db;
  border-radius: 50%;
  width: 40px;
  height: 40px;
  animation: spin 0.6s linear infinite;
  display: inline-block;
  margin: 8px auto;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
// 声明常量MAX_PAGES,表示可加载的最大页数
const MAX_PAGES = 5;

// 生成随机颜色的函数
const generateRandomColor = () => {
  const characters = "0123456789ABCDEF";
  let color = "#";
  for (let i = 0; i < 6; i++) {
    color += characters[Math.floor(Math.random() * 16)];
  }
  return color;
};

// 定义Item组件,接受children、color和reference属性,返回带有颜色的div元素
const Item = ({ children, color, reference }) => {
  return (
    <div className="item" style={{ backgroundColor: color }} ref={reference}>
      {children}
    </div>
  );
};

// 定义App组件
const App = () => {
  // 定义状态变量:items-加载的数据数组、isLoading-是否正在加载数据、hasMore-是否还有更多数据可加载、pages-已加载的页数
  const [items, setItems] = React.useState([]);
  const [isLoading, setIsLoading] = React.useState(false);
  const [hasMore, setHasMore] = React.useState(true);
  const [pages, setPages] = React.useState(0);

  // 定义ref引用observer
  const observer = React.useRef();

  // 在挂载时更新items数组和pages变量
  React.useEffect(() => {
    updateItems();
    setPages((pages) => pages + 1);
  }, []);

  // 定义lastItemRef回调函数,用于观察最后一个元素是否进入视口
  const lastItemRef = React.useCallback(
    (node) => {
      if (isLoading) return;
      if (observer.current) observer.current.disconnect();

      observer.current = new IntersectionObserver((entries) => {
        if (entries[0].isIntersecting && hasMore) {
          if (pages < MAX_PAGES) {
            updateItems();
            setPages((pages) => pages + 1);
          } else {
            setHasMore(false);
          }
        }
      });

      if (node) observer.current.observe(node);
    },
    [isLoading, hasMore]
  );

  // 定义updateItems异步函数,更新items数组和isLoading状态变量
  const updateItems = async () => {
    setIsLoading(true);
    await new Promise((resolve) => setTimeout(resolve, 1000));

    setItems((currItems) => {
      const lastItem = currItems.length;
      const updatedItems = [...currItems];
      for (let i = 1; i <= 5; i++) {
        const item = {
          count: lastItem + i,
          color: generateRandomColor()
        };
        updatedItems.push(item);
      }
      return updatedItems;
    });

    setIsLoading(false);
  };

  // 返回页面结构
  return (
    <React.Fragment>
      <h1>Infinite Scroll Demo</h1>
      {items.map((item, index) =>
        index + 1 === items.length ? (
          <Item reference={lastItemRef} key={index} color={item.color}>
            {item.count}
          </Item>
        ) : (
          <Item key={index} color={item.color}>
            {item.count}
          </Item>
        )
      )}
      {isLoading && <div className="loader" />}
    </React.Fragment>
  );
};

// 将App组件渲

注意:此示例使用React,因为这是我个人偏好,但你可以使用任何框架或原生JavaScript。

4、Clipboard API

Clipboard API 允许你读取和写入剪贴板中的数据。这对于实现复制到剪贴板的功能非常有用。

// 定义异步函数copyHandler,将指定文本写入剪贴板
async function copyHandler() {
  const text = "https://tapajyoti-bose.vercel.app/";
  navigator.clipboard.writeText(text);
}

5、Screen Wake Lock API

你是否曾经想过在观看视频时如何防止屏幕关闭?这就是因为使用了 Screen Wake Lock API。

// 声明变量wakeLock
let wakeLock = null;

// 定义异步函数lockHandler,请求屏幕唤醒锁定
async function lockHandler() {
  wakeLock = await navigator.wakeLock.request("screen");
}

// 定义异步函数releaseHandler,释放屏幕唤醒锁定
async function releaseHandler() {
  await wakeLock.release();
  wakeLock = null;
}

// 注意:只有页面已经在屏幕上可见时,才能使用Screen Wake Lock API。否则会抛出错误。

6、Screen Orientation API

Screen Orientation API 允许你检查屏幕的当前方向,甚至锁定到特定的方向。

// 定义异步函数lockHandler,锁定屏幕方向为竖屏
async function lockHandler() {
  await screen.orientation.lock("portrait");
}

// 定义函数releaseHandler,解除屏幕方向锁定
function releaseHandler() {
  screen.orientation.unlock();
}

// 定义函数getOrientation,返回屏幕当前的方向
function getOrientation() {
  return screen.orientation.type;
}

7、Fullscreen API

Fullscreen API 允许你将一个元素或整个页面显示为全屏。

// 定义异步函数enterFullscreen,将整个文档元素进入全屏模式
async function enterFullscreen() {
  await document.documentElement.requestFullscreen();
}

// 定义异步函数exitFullscreen,退出全屏模式
async function exitFullscreen() {
  await document.exitFullscreen();
}

// 注意:为了使用 Fullscreen API,同样需要用户的交互。

注意:同样需要用户的交互才能使用 Fullscreen API。

兼容性

这些API,目前在主流浏览器中都得到了很好的支持,包括Google Chrome、Mozilla Firefox、Safari和Microsoft Edge等浏览器。但是,在旧版浏览器中可能会存在一些兼容性问题。因此,在开发使用时,应该考虑到不同浏览器的兼容性问题,并根据实际情况选择是否使用这些API。

结束

非常棒!通过本文的介绍和代码示例,相信大家已经了解了这些有用的Web API,并且知道如何使用它们来提升网站的用户体验和功能。虽然这些API在不同浏览器中的兼容性可能存在一些问题,但我们可以通过适当的兼容性检查和回退方案来确保网站的稳定性和可靠性。总之,Web API为开发者提供了强大的工具和资源,让我们一起探索并不断尝试新的技术和功能,为用户带来更好的体验和价值。

今天的分享就到这里,感谢你的阅读,希望能够帮助到你,文章创作不易,如果你喜欢我的分享,别忘了点赞转发,让更多有需要的人看到,最后别忘记关注「前端达人」,你的支持将是我分享最大的动力,后续我会持续输出更多内容,敬请期待。

原文:https://tapajyoti-bose.medium.com/7-javascript-web-apis-to-build-futuristic-websites-you-didnt-know-12b737ccf594

作者:Tapajyoti Bose

非直接翻译,有自行改编和添加部分,翻译水平有限,难免有疏漏,欢迎指正