Promise 和 Async await
当谈到在 Javascript 中密切相关的概念 Promises 和 Async await 时,人们总是感到困惑,甚至在看了教程或阅读了

当谈到在 Javascript 中密切相关的概念 Promises 和 Async await 时,人们总是感到困惑,甚至在看了教程或阅读了大量关于它们的文章之后。好吧,不要担心,因为我向你保证,如果你仔细阅读这篇文章,你会更好地理解它们是什么以及它们是如何工作的。

验证同步还是异步
js
let numbers = [1, 2, 4, 7, 3, 5, 6]
numbers.sort((a, b) => a - b)
console.log(numbers); // [ 1, 2, 3, 4, 5, 6, 7 ]
函数 sort ()有一个匿名箭头函数,作为一个回调函数对数组进行排序,我们在控制台上打印它。注意,箭头函数在控制台前运行,因此我们得到了排序数组,但是如果你用 setTimeout 对相同的数组排序,那么控制台将打印未排序的数组:
js
let numbers = [2, 1, 4, 7, 3, 5, 6]
// numbers.sort((a, b) => a - b)
setTimeout((a,b) => {
numbers.sort((a,b) => a-b)
// console.log(numbers)
}, 0)
console.log(numbers); // [2, 1, 4, 7, 3, 5, 6]
这是因为异步代码在所有同步代码执行完毕之后运行,这就是为什么尽管 setTimeout 有0等待时间,但它仍然在 console.log 之后运行,尽管 console.log 在代码中后来才出现
只要异步操作很少,回调对于异步编程是有用的,但是如果你想异步运行更多的函数,那么回调就会变成一团糟!
js
const url1 = 'https://fakeapi.com/1/'
const url2 = 'https://fakeapi.com/2/'
const url3 = 'https://fakeapi.com/3/'
function callback(url,msg){
// calls api here
console.log(msg)
}
setTimeout(() => {
callback('first message')
setTimeout( () => {
callback('second message')
setTimeout( () => {
callback('third message')
},0)
}, 0)
},0)
// first message
// second message
// third message
Promise 对象可以由 Promise ()构造函数生成,该构造函数接受一个 executor 函数,该函数接受两个函数作为参数: 一个 resolve 函数和一个 reject 函数。这就是你做出新承诺的方式:
js
const aPromise = new Promise( (resolve, reject) => {
resolve("promise resolved")
})
aPromise.then(( value) => {
console.log(value)
})
.catch( (error) => {
console.log(error)
})
这个“ executor”函数根据 Promise 的值调用 resolve 或 reject 函数来终止,这意味着执行函数运行一些代码,如果 Promise 得到解析,则调用 resolve 函数; 如果 Promise 抛出错误,则调用 reject 函数。
js
aPromise.then(( value) => {
return value = 'changed value'
})
.then((value) => {
console.log(value)
})

我们通常在进行 api 调用时使用这些方法。让我们使用 fetch API 从 PokeAPI 获取 Pokemon 的列表。获取()。函数返回一个 Promise,这样我们就可以将。然后()及。Catch ()方法:
js
const url = 'https://pokeapi.co/api/v2/pokemon?limit=100&offset=200'
fetch(url)
.then((response) => {
response.json()
})
.then((data) => {
console.log(data)
})
这样我们就可以得到100个带有其他属性的口袋妖怪列表。承诺确实让我们的生活变得更加容易,但是我们的代码看起来仍然有很多的链接方法。Asyncawait 使得这个过程更加简洁,并且允许我们编写看起来非常像我们的老式同步代码的异步代码。
Async await 异步等待
用异步等待来代替。然后()及。在处理 Promises 时 catch ()。我们需要分配一个 ASYNC 函数,然后在其中,我们可以在要执行的异步操作之前使用 await 关键字(这意味着我们认为可能需要更长时间的代码)。像这样:
js
const loadData = async () {
const url = 'https://jsonplaceholder.com/todos/1/'
const res = await fetch(url)
const data = res.json()
console.log(data)
}
loadData()
try-catch block 试接块
就像。Catch ()块,我们在 Promises 中使用,在 Async 使用 try-catch 处理错误。这使得代码更加清晰和有组织。
js
const loadData = async () {
try{
const url = 'https://jsonplaceholder.com/todos/1/'
const res = await fetch(url)
const data = await res.json()
console.log(data)
}
catch(err){
console.error(err)
}
}
Promise.all()
如果您需要向一个 API 发出多个请求,并且采用异步等待的方法,那么所有请求返回数据所需的时间总和就是这个时间。假设每个请求需要1秒,对于3个请求,如果我们只是等待每个请求,我们将不得不等待3秒:
js
/* Wrong approach */
const loadData = async() {
try(){
const url = 'https://jsonplaceholder.com/todos/1/'
const url2 = 'https://jsonplaceholder.com/todos/2/'
const url3 = 'https://jsonplaceholder.com/todos/3/'
const res = await fetch(url)
const res2 = await fetch(url2)
const res3 = await fetch(url3)
const data = await res.json()
const data2 = await res2.json()
const data3 = await res3.json()
return [data, data2, data3]
}
catch(err){
console.error(err)
}
}
通过 Promise.all () ,每个请求彼此并行运行,从而得到更快的响应
js
/* Right approach */
const loadData = async() {
try(){
const url = 'https://jsonplaceholder.com/todos/1/'
const url2 = 'https://jsonplaceholder.com/todos/2/'
const url3 = 'https://jsonplaceholder.com/todos/3/'
const results = await Promise.all([
fetch(url),
fetch(url2),
fetch(url3)
])
const dataPromises = results.map( res => res.json())
const finalData = await Promise.all(dataPromises)
return finalData
}
catch(err){
console.error(err)
}
}
( async() => {
const data = await loadData()
console.log(data)
})()