如何从 JavaScript 中的异步调用返回响应?
JavaScript 是一种单线程编程语言,异步编程是构建该语言的基本概念。 JavaScript 内置了三种处理异步调用的方法,如下所示:
- 回调函数
- 使用 .then() 和 .catch() 方法进行 Promise 和 Promise 处理
- 使用 await 的 ES6+/ESNext 风格的异步函数
在本文中,我们将讨论如何以上述所有方式处理异步调用。我们将使用 Node.js 中提供的请求模块从网站 DOG CEO API 请求 JSON 数据,该 API 返回 JSON 格式的随机狗图片的 URL 链接。
- 使用回调函数:
// Callback method const request = require('request'); const url ='https://dog.ceo/api/breeds/image/random'; function callback(res, body) { console.log(JSON.parse(body)); } function getData(callback) { // Using the request module to request // data asynchronously request(url, (err, res, body) => { if (err) throw err; callback(res, body); }); } // Here we call the getData function // with the callback function getData(callback); console.log('asynchronous is awesome');
输出:
asynchronous is awesome { message: 'https://images.dog.ceo/breeds/vizsla/n02100583_11450.jpg', status: 'success' }
说明:在这个方法中,我们请求 JSON 数据的 API,并使用回调函数对数据执行函数。为了便于理解,我们只是将接收到的数据记录到控制台,但可以执行各种其他功能。这整个过程是异步发生的。命令
console.log('asynchronous is awesome');
虽然放置在对函数getData 的调用之后,但在 getData 完成之前执行。 - 将 Promises 与 .then() 和 .catch() 方法一起使用:
// Promise with then catch const promise = new Promise((resolve, reject) => { request(url, (err, res, body) => { if (err) return reject(err); try { resolve(JSON.parse(body)); } catch(error) { reject(error); } }); }); promise.then((data) => { console.log(data); }) .catch((err)=>{ console.error(err); }); console.log('asynchronous is awesome');
输出:
asynchronous is awesome { message: 'https://images.dog.ceo/breeds/pointer-germanlonghair/hans2.jpg', status: 'success' }
说明:请求模块本身不返回承诺。因此,我们使用 Promise 构造函数将从 HTTP 请求接收到的可能响应包装到本机 Promise 中。然后使用 .then() 和 .catch() 方法处理此承诺。使用这种方法的优点是多方面的。首先,使用 .then() 和 .catch() 方法解决 Promise 是错误处理的最佳实践,有助于我们以错误优先的心态编写代码。其次,JavaScript 模块正在适应支持 Promise 并丢弃旧的回调样式错误处理。 Axios、fetch 等较新的模块仅支持 Promise。同样,Promises 是一种相对较新的异步代码编写方式。命令
console.log('asynchronous is awesome');
证明了这一点。虽然放置在对 promise 处理程序的调用之后,但在 promise 完成之前执行。 - 使用 await 的 ES6+/ESNext 风格的异步函数:
const getData = async () => { let data = await new Promise((resolve, reject) => { request(url, (err, res, body) => { if (err) return reject(err); try{ resolve(JSON.parse(body)); } catch(error) { reject(error); } }); }); try{ console.log(data); } catch(err){ console.error(err); } } getData(); console.log('asynchronous is best');
输出:
asynchronous is awesome { message: 'https://images.dog.ceo/breeds/sheepdog-shetland/n02105855_15196.jpg', status: 'success' }
说明: Javascript 中的异步函数允许我们坚持传统的编程策略,例如使用 for、while 和其他本质上是同步的并且不能在 Javascript 中使用的方法。在此示例中,我们将 HTTP 请求返回的可能响应包装在一个 Promise 中。由于 promise 需要一定的时间来解决或拒绝,我们使用 await 关键字来等待 promise 返回响应。最佳实践是使用 try()/catch() 序列来处理使用 await 后从 Promise 收到的响应,以帮助我们处理错误(如果有)。虽然同步代码可以写在 try()/catch() 序列中,但是 async函数是异步执行的,这一点可以通过命令
console.log('asynchronous is awesome');
来证明。虽然放置在对函数getData 的调用之后,但在异步函数完成之前执行。