厌倦了理清 JAVAScript 或 TypeScript 项目中的异步代码?
您是否希望有一种方法可以使您的异步进程像运转良好的机器一样运行? 如果是这种情况,我们为您提供了一个解决方案:promises - 任何出色的异步配方中的关键成分。 它们让您以更有序和更易于理解的方式管理异步操作,让您专注于编码的更有趣的方面。 我们将在本文中带您游览狂野而美丽的promises世界。
什么是承诺?
在 JavaScript 中,promise 是一种以更有条理、更易于理解和更简洁的方式处理异步操作的方法。 它们使您能够构建以可预测的顺序方式运行的代码,即使操作本身是并行发生的。
Promise 是通过将函数作为参数传递给 Promise 构造函数来创建的。 这个函数被称为执行函数,它负责执行异步操作。 执行函数有两个参数:resolve 和 reject。 这些功能用于履行(解决)或拒绝承诺。
以下面的例子为例,其中一个承诺是用一个等待 3 秒的执行函数创建的,然后用“Hey!My name is Bruno.”的值解析promise:
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Hey!My name is Bruno.");
}, 3000);
});
在创建承诺后,您可以使用 then() 方法来告诉它在解决或拒绝时做什么。 作为参数,它需要两个函数:一个用于 resolve 分支,一个用于 refuse 分支。
考虑以下场景,其中 resolve 分支打印消息“Hey!My name is Bruno.”,而 reject 分支在另一方面记录一条错误消息:
myPromise.then(
(message) => {
console.log(`The promise has been resolved: ${message}`)
},
(error) => {
console.log(`The promise has been rejected: ${error}`)
}
);
链接promise允许您创建一系列异步操作,这些操作按顺序/一个接一个地执行。
myPromise
.then((message) => {
console.log(message); // Hey!My name is Bruno.
return message + " I am a software developer."
})
.then((message) => {
console.log(message); // Hey!My name is Bruno. I am a software developer.
})
上面的prmise是链接的,第一个 then() 记录消息的第一个版本,而第二个 then() 记录与 return 语句中的字符串连接的消息。
现在让我们继续讨论 promise 的一些用例。
在不同的情况和场景中,可以使用 promises 来执行异步操作。
可以以一种干净且易于理解的方式处理 HTTP 请求。 我们将使用 AxIOS 库来说明一个示例,它基本上与已经内置的 fetch() 执行相同的操作:
import axios from "axios";
const API_URL = "dummyapithatdoesnotexist.com/data";
axios.get(API_URL)
.then((response) => response.json())
.then((jsonData) => console.log(jsonData)) // data from the API
.catch((error) => console.log(`There has been an error: ${error}`));
请注意 promise 末尾的“catch()”方法。“catch()”用于处理在尝试解析 promise 时发生的任何错误。 它非常有价值,也是异步操作的一个重要方面,因为它提供了为什么它们没有成功的上下文(例如,当没有互联网连接或服务器关闭时)。
当然还有其他场景可以使用 promises,但这个场景很好地说明了一个广为人知的场景。
您现在可能会问自己:但是……JavaScript 和 Typescript 中的 promises 有什么区别?
好吧,当然,这是一个很好的问题,我们现在将讨论这个问题。
为了创建承诺,JavaScript 和 TypeScript 都使用 Promise 构造函数,并且两种语言都使用 then() 方法来指示在解决或拒绝承诺时应该发生什么。
JavaScript 承诺和 TypeScript 承诺之间的一个重要区别是,在 TypeScript 中,您使用更强大的类型检查,这有助于防止代码中的错误和错误。 这可以避免在一天结束前一直头痛的困扰(到底哪里错了?)。 更强的类型允许您声明 promise 将解析或拒绝的值类型,而 JavaScript 依赖于运行时类型检查。 这是在项目中使用 JavaScript 或 Typescript 时要牢记的一个重要方面。
Typescript 中类型化承诺的示例如下所示:
import axios from "axios";
const API_URL: string = "dummyapithatdoesnotexist.com/data";
const myPromise: Promise<string> = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Hey!My name is Bruno.");
}, 3000);
});
在指定 then() 和 catch() 场景时,您还可以按以下方式键入它们:
import axios from "axios";
const API_URL: string = "dummyapithatdoesnotexist.com/data";
axios.get(API_URL)
.then((response: Response) => response.json())
.then((jsonData: any) => console.log(jsonData)) // data from the API
.catch((error: any) => console.log(`There has been an error: ${error}`));
在 Typescript 中,您还可以使用 async 和 await,前者允许您指示操作是异步的,后者会暂停函数的执行,直到 promise 得到解决。
import axios from 'axios';
const API_URL: string = 'dummyapithatdoesnotexist.com/data';
async function getData() {
try {
const response: AxiosResponse = await axios.get(API_URL);
const jsonData: any = response.data;
console.log(jsonData);
} catch (error) {
console.log(`There has been an error: ${error}`);
}
}
getData(); // logs the data from the API
AxiosResponse 类型是从 axios 库中导入的,用于键入本示例中的响应变量。 要从 API 响应中获取 JSON 数据,请使用 response.data 属性。 jsonData 变量是 any 类型,表明它可以保存任何类型的值。 error 变量的类型也为 any,暗示它也可能是任何类型。
async 关键字将 getData() 函数标识为异步函数,而 await 关键字暂停函数的执行,直到承诺得到解决。 如果在请求期间发生错误,catch() 块会检测到错误并将其记录到控制台。
在了解了 JavaScript 和 Typescript 中所有这些 promises 的点点滴滴之后,您现在应该能够在代码中以非类型化或类型化的方式应用它们。 恭喜,希望对您有所帮助!