Node.js不同异步函数间使用全局变量是否属于最佳实践?
方案说明
全局变量方案是否符合最佳实践
不符合,该方案存在几个明显问题:
- 全局变量极易被其他逻辑意外修改,后期排查问题成本极高
- 异步执行时序不可控,若在爬取未完成时读取全局变量,会拿到
undefined,引发非必现bug - 代码耦合度过高,两个函数无法单独复用、单独测试
推荐实现方案
直接改造read_fortune_500函数,将爬取到的结果作为返回值返回,异步函数返回的是Promise对象,调用时通过await拿到结果后,直接作为参数传入getCurrentPrice即可,完全不需要引入全局变量。
修改后的代码如下:
const cheerio = require('cheerio'); const axios = require("axios"); async function read_fortune_500() { try { const { data } = await axios({ method: "GET", url: "https://en.wikipedia.org/wiki/List_of_S%26P_500_companies" }) const $ = cheerio.load(data) const elemSelector = '#constituents > tbody > tr > td:nth-child(1)' const keys = ['symbol'] // 新增结果数组存储爬取到的数据 const stockList = [] $(elemSelector).each((parentIndex, parentElem) => { let keyIndex = 0 const stockObject = {} if (parentIndex <= 9){ $(parentElem).children().each((childIndex, childElem) => { const tdValue = $(childElem).text() if (tdValue) { stockObject[keys[keyIndex]] = tdValue } }) // 把单条数据存入结果数组 stockList.push(stockObject) } }) // 返回结果数组 return stockList } catch (err) { console.error(err) // 异常场景返回空数组避免上层调用报错 return [] } } async function getCurrentPrice(stockList) { // 直接用传入的stockList遍历拉取雅虎财经对应数据即可 for (const stock of stockList) { console.log('当前处理股票代码:', stock.symbol) // 此处补充雅虎财经拉取逻辑 } } // 统一入口控制异步时序 (async () => { const stockList = await read_fortune_500() await getCurrentPrice(stockList) })()
优化点说明
- 无全局变量污染,两个函数职责独立,可单独测试、单独复用
- 通过async自执行函数统一控制执行时序,保证爬取完成后才会执行拉取价格的逻辑,不会出现时序错误
- 异常场景做了兼容处理,不会因为爬取失败导致后续逻辑崩溃
内容的提问来源于stack exchange,提问作者Dave Michaels
相关产品推荐
相关产品推荐

