主题
承诺(Promises)
承诺
我们人类会给出或接受承诺在某个时间点做某些活动。如果我们遵守承诺,我们会让别人高兴,但如果我们不遵守承诺,可能会导致不满。JavaScript 中的 Promise 与上述示例有一些共同点。
Promise 是在 JavaScript 中处理异步操作的一种方式。它允许处理程序处理异步操作的最终成功值或失败原因。这让异步方法像同步方法一样返回值:异步方法不是立即返回最终值,而是返回一个承诺在将来某个时间点提供该值。
Promise 处于以下状态之一:
- pending(待定):初始状态,既未完成也未拒绝。
- fulfilled(已完成):意味着操作成功完成。
- rejected(已拒绝):意味着操作失败。
待定的 promise 可以用值完成,或者用原因(错误)拒绝。当这些选项中的任何一个发生时,由 promise 的 then 方法排队的相关处理程序将被调用。(如果在附加相应处理程序时 promise 已经完成或拒绝,则将调用处理程序,因此异步操作完成和其处理程序附加之间没有竞争条件。)
由于 Promise.prototype.then() 和 Promise.prototype.catch() 方法返回 promises,它们可以被链式调用。
回调函数
为了很好地理解 promise,让我们首先理解回调。让我们看看以下回调。从以下代码块中,你会注意到回调和 promises 之间的区别。
- 回调 让我们看一个可以接受两个参数的回调函数。第一个参数是 err,第二个是 result。如果 err 参数为 false,则不会有错误,否则它将返回错误。
在这种情况下,err 有一个值,它将返回 err 块。
js
//回调
const doSomething = callback => {
setTimeout(() => {
const skills = ['HTML', 'CSS', 'JS']
callback('It did not go well', skills)
}, 2000)
}
const callback = (err, result) => {
if (err) {
return console.log(err)
}
return console.log(result)
}
doSomething(callback)
sh
// 2秒后它将打印
It did not go well
在这种情况下,err 为 false,它将返回 else 块,即结果。
js
const doSomething = callback => {
setTimeout(() => {
const skills = ['HTML', 'CSS', 'JS']
callback(false, skills)
}, 2000)
}
doSomething((err, result) => {
if (err) {
return console.log(err)
}
return console.log(result)
})
sh
// 2秒后它将打印技能
["HTML", "CSS", "JS"]
Promise 构造函数
我们可以使用 Promise 构造函数创建一个 promise。我们可以使用关键字 new
后跟单词 Promise
再后跟括号来创建一个新的 promise。在括号内,它接受一个 callback
函数。promise 回调函数有两个参数,即 resolve
和 reject
函数。
js
// 语法
const promise = new Promise((resolve, reject) => {
resolve('success')
reject('failure')
})
js
// Promise
const doPromise = new Promise((resolve, reject) => {
setTimeout(() => {
const skills = ['HTML', 'CSS', 'JS']
if (skills.length > 0) {
resolve(skills)
} else {
reject('Something wrong has happened')
}
}, 2000)
})
doPromise
.then(result => {
console.log(result)
})
.catch(error => console.log(error))
sh
["HTML", "CSS", "JS"]
上述 promise 已通过 resolve 解决。 让我们再看一个当 promise 通过 reject 解决的例子。
js
// Promise
const doPromise = new Promise((resolve, reject) => {
setTimeout(() => {
const skills = ['HTML', 'CSS', 'JS']
if (skills.includes('Node')) {
resolve('fullstack developer')
} else {
reject('Something wrong has happened')
}
}, 2000)
})
doPromise
.then(result => {
console.log(result)
})
.catch(error => console.error(error))
sh
Something wrong has happened
Fetch API
Fetch API 提供了一个用于获取资源(包括跨网络)的接口。对于任何使用过 XMLHttpRequest 的人来说,它都会很熟悉,但新的 API 提供了更强大和灵活的功能集。在这个挑战中,我们将使用 fetch 来请求 url 和 API。除此之外,让我们看看使用 fetch API 访问网络资源时 promises 的使用案例演示。
js
const url = 'https://restcountries.com/v2/all' // 国家 api
fetch(url)
.then(response => response.json()) // 将 API 数据作为 JSON 访问
.then(data => {
// 获取数据
console.log(data)
})
.catch(error => console.error(error)) // 如果出现问题则处理错误
Async 和 Await
Async 和 await 是处理 promises 的优雅方式。它易于理解且编写简洁。
js
const square = async function (n) {
return n * n
}
square(2)
sh
Promise {<resolved>: 4}
函数前面的单词 async 意味着该函数将返回一个 promise。上面的 square 函数不是返回值而是返回 promise。
我们如何从 promise 中访问值?要从 promise 中访问值,我们将使用关键字 await。
js
const square = async function (n) {
return n * n
}
const value = await square(2)
console.log(value)
sh
4
现在,正如你从上面的例子中看到的,在函数前面写 async 创建一个 promise,要从 promise 中获取值,我们使用 await。Async 和 await 是一起的,一个不能没有另一个而存在。
让我们使用 promise 方法和 async 和 await 方法获取 API 数据。
- promise
js
const url = 'https://restcountries.com/v2/all'
fetch(url)
.then(response => response.json())
.then(data => {
console.log(data)
})
.catch(error => console.error(error))
- async 和 await
js
const fetchData = async () => {
try {
const response = await fetch(url)
const countries = await response.json()
console.log(countries)
} catch (err) {
console.error(err)
}
}
console.log('===== async and await')
fetchData()
🌕 你是真实的,你遵守了你的承诺,你到达了第18天。遵守你的承诺并通过 resolve 解决挑战。你在通往伟大的道路上已经前进了18步。现在为你的大脑和肌肉做一些练习。
练习
js
const countriesAPI = 'https://restcountries.com/v2/all'
const catsAPI = 'https://api.thecatapi.com/v1/breeds'
练习:第1级
- 使用 fetch 读取国家 API 并打印国家名称、首都、语言、人口和面积。
练习:第2级
- 将所有猫的名字打印到 catNames 变量中。
练习:第3级
- 读取猫 api 并找到猫在公制单位中的平均重量。
- 读取国家 api 并找出10个最大的国家
- 读取国家 api 并计算世界上用作官方语言的语言总数。
🎉 恭喜!🎉