💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
## Promise Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了`Promise`对象。 所谓`Promise`,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。 有了`Promise`对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,`Promise`对象提供统一的接口,使得控制异步操作更加容易。 ### 简单示例 ``` function p (num) { return new Promise((resolve, reject) => { if (num >= 0) { resolve(num) } else { reject(new Error('参数不能小于 0')) } }) } ``` 这里,返回了一个 Promise 对象,如果成功将执行 resolve(num),使用的时候用 then 接收,如果失败,执行 reject() 并抛出一个错误。 成功的调用 ``` console.log('-1-') p(10).then(num => { console.log(num) }).catch(e => { console.log(e) }) console.log('-2-') ``` 输出 ``` -1- -2- 10 ``` 失败的调用 ``` console.log('-1-') p(-1).then(num => { console.log(num) }).catch(e => { console.log(e) }) console.log('-2-') ``` 输出 ``` -1- -2- Error: 参数不能小于 0 ``` ### Promise 新建后就会立即执行 ``` let promise = new Promise(function(resolve, reject) { console.log('Promise'); resolve(); }); promise.then(function() { console.log('resolved.'); }); console.log('Hi!'); ``` 输出 ``` Promise Hi! resolved ``` 上面代码中,Promise 新建后立即执行,所以首先输出的是Promise。然后,then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行,所以resolved最后输出。 ### 可以在 .then 回调里返回 Promise 可以在 then 回调里返回 Promise!返回的 promise 会在接下来的 then 被自动打开(unwrapped) 示例,函数仍然使用上述 p() 函数 ``` console.log('-1-') p(10).then(num => { console.log(num) return p(15) }).then(num => { console.log(num) return p(-5) }).catch(e => { console.log(e) }) console.log('-2-') ``` 输出 ``` -1- -2- 10 15 Error: 参数不能小于 0 ``` ### 每次调用 .then 都会产生一个新的 Promise 在链式调用 Promise 时,可以不显示声明 return 语句,then 默认会返回一个 Promise 示例,函数仍然使用上述 p() 函数 ``` p(10).then(num => (num >= 10 ? 'ok' : 'no')) .then(console.log) p(1).then(num => (num >= 10 ? 'ok' : 'no')) .then(console.log) ``` 输出 ``` ok no ``` 注意,每次调用 then 返回的都是不同的 Promise 实例,即 p() 、'ok'、'no' 返回的是三个不同的 Promise 实例,如果 p 出错,则会被 rejected,但 p().then 中返回的都是 resolve。 ### 将 callback API 转换为 Promise 在 Node.js 中,推荐使用 util.promisify。用来将回调 API 转成 promise 式的: ``` const { promisify } = require('util'); const fs = require('fs'); const readFileAsync = promisify(fs.readFile); readFileAsync('myfile.txt', 'utf-8') .then( r => console.log(r) ) .catch( e => console.error(e)); ``` ### Promise.prototype.finally() finally 方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。 ``` promise .then(result => {···}) .catch(error => {···}) .finally(() => {···}) ``` 不管promise最后的状态,在执行完then或catch指定的回调函数以后,都会执行finally方法指定的回调函数。