{"_id":"@9f/singleflight","_rev":"2-926625febc4424424b07eb2653d0f20c","name":"@9f/singleflight","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@9f/singleflight","version":"1.0.0","description":"provides a duplicate function call suppression mechanism.","main":"index.js","scripts":{"test":"node test/index.js"},"repository":{"type":"git","url":"git+https://github.com/leekafai/singleflight.git"},"author":{"name":"leekafai"},"license":"MIT","bugs":{"url":"https://github.com/leekafai/singleflight/issues"},"homepage":"https://github.com/leekafai/singleflight#readme","devDependencies":{"eslint":"^7.24.0"},"gitHead":"7ff582fee4eaa16174a0ed11ade3fd37f77952c9","_id":"@9f/singleflight@1.0.0","_nodeVersion":"14.15.5","_npmVersion":"7.9.0","dist":{"integrity":"sha512-t2+DxLGW+RwVxSH8bDNcAw33F4j04rk8r6/Wo8qYxpBg3w0bUoeFYlQn7pMNp9hK2NPwMCG+Sy5PqhgZrbqMFQ==","shasum":"167e2c238e4a79a38886e12fc4330e2cd290629a","tarball":"https://registry.npmjs.org/@9f/singleflight/-/singleflight-1.0.0.tgz","fileCount":10,"unpackedSize":13159,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJghoihCRA9TVsSAnZWagAAQtMP/iigVknpjyGbcozy42AL\n7NndFgwk1XNp5vBuX7jBXTMLqqBLtzY/6GgwhmMjwodjNQR+3A3EdGGvXMm9\nkiFdy7B/hxOELDUe0H3Qjog4SP1Vh223KtcUE2e3YnfTRaJsiNaeUVzgE3IL\ns0NOgXrt3THD3BEv+2BjL3XmbZHhPIg4vXd8KG22gr+4ZQScGVnNA9o9GOXx\nFoYS3+4pG0r0vUWDHEUTxUZ3RzmLFTb9QhCd5G2RyElUIxeryGN4RvRwGjlU\nZ5Zc8XZlJ+sTaOzMNL6v5L0y7Vrk4WoI8O5mMvzfUtVcm/i5Rx4UsRAbkSjn\n1aMacl1zjOlgVAidsqCzUAfnmZZiT0XC6wjASwO5p6gZTa6RxA817gxJKFM+\nT2svUdahvP8Qpc+wc/xKJnbvbxi1x5skqwo+6pDnj977y1js0wXevO2urMgj\ny32rMDNg7Vth2zOium/iRTRleGPaTCWK8cgrAcK5XG7NGFZdrw7v3pIZFKx+\nBxNhQvjHBFFZRxVgWFCin2qtfCvfDUPG3DbK3x1YtOU41NTOOGisn7J4VJ3s\nMK6KMV9p+mShhk51dAff2YmqP1ptTNJU3ZqY7wWzC0bv+ZJvzo7R2DKtXzdb\nT8uB5ZU+vpElDN2cTOu2mS4U6f4cU7WTr4SGLat/lrKtlexc9CPlfjy6ToYL\nM97Z\r\n=F3RD\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCpfhhzGT1HYZ2v5SLxXrvEEOBR+JQVE5nlBiThzNYGkgIhAMkfzin026a2I72FpHwG2uujuuzTKl2IxC0Eo8XhedC0"}]},"_npmUser":{"name":"leekafai","email":"leekafai@outlook.com"},"directories":{},"maintainers":[{"name":"leekafai","email":"leekafai@outlook.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/singleflight_1.0.0_1619429536616_0.0831845713974595"},"_hasShrinkwrap":false},"1.0.1":{"name":"@9f/singleflight","version":"1.0.1","description":"provides a duplicate function call suppression mechanism.","main":"index.js","scripts":{"test":"node test/index.js"},"repository":{"type":"git","url":"git+https://github.com/leekafai/singleflight.git"},"author":{"name":"leekafai"},"license":"MIT","bugs":{"url":"https://github.com/leekafai/singleflight/issues"},"homepage":"https://github.com/leekafai/singleflight#readme","devDependencies":{"eslint":"^7.24.0"},"gitHead":"1dad49666429c01b7f4cd5ff52bdae2069136847","_id":"@9f/singleflight@1.0.1","_nodeVersion":"14.15.5","_npmVersion":"7.9.0","dist":{"integrity":"sha512-qIHv0EdvPLU0VX71T7ss0N0zBcuBzprR+XQoH3+8AsMYI2e7SZZso92hLP1Paq07Bx7KO8eKHxlHEJzicGWjZg==","shasum":"0277f896944de15375af1ff47210092f30581c2d","tarball":"https://registry.npmjs.org/@9f/singleflight/-/singleflight-1.0.1.tgz","fileCount":9,"unpackedSize":11251,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJghom/CRA9TVsSAnZWagAAykUP/AuszFc9blRSsiWQMG5z\nCgU3oSlQ8en3WF9+1QSe7r4GHvZPfFyFVW7Osjpnrh7/idFAv4rWepir+2cm\nXGWk+XaaLih44lQPOi9ED64tuyjbY38KU7dkHcjmd203ESwsOAy7oLSicOTX\nncrt3AMDzijArR2nsHe0Rc3STJ7bU/zqakn4PsiqCp/dAQew6uutnoUs1o+W\njSQli8ewro4iCCcD5HfzPKNRkZriQ8tPbTBolH1VDNOb4Bg3P2HuC55XfNiR\nqnJDOybLz0JAv/jG/yf+26W0pokJWDqVTdD3cjd7/LCgBHgQaET0p7nmbrAn\nLHBEVkjGqseM9hhLwJMMFXNJbTk1XX6zlVxmdXP/Gt7RzXEBS5Jy1kFoX9R5\nHplSNQCA5iX1aje11xxfVQscYseYUT8d8b1uUnoU0L5a+oBYA37Q1Vkbwmhp\nQRgD+fJkjp257PJfc1dCqPF8U4sW7BmD+T7AsHZQyhVOXKZb47R4JrGOotkV\nKoPrd95LFiYp6iC0vTJS2RSDKvBFBXGO1//+gXCy9yC+VrOP27ACGqEObGl+\ndcWoulaME62daSiOqLR4NroWrChmgdgJw51xDdU33vEKaSzUselbLaGU3Nhj\n1JYqGi2o1J6Jz6b+JYVmUkjQquwOzhwwDLmDnO9MDB+fLGXSgVOtI5R1lRt6\nCzSx\r\n=FScn\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCFGFdqyIrlG7KgQZoaYo9j7ffBcmN+SvTo2Sr1NEPXNwIgOqlM0uaIk4pmN1oWOJG1lj/Yb4WX6E09TwEm9JLr9U0="}]},"_npmUser":{"name":"leekafai","email":"leekafai@outlook.com"},"directories":{},"maintainers":[{"name":"leekafai","email":"leekafai@outlook.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/singleflight_1.0.1_1619429822617_0.3347390913237325"},"_hasShrinkwrap":false}},"time":{"created":"2021-04-26T09:32:16.279Z","1.0.0":"2021-04-26T09:32:16.784Z","modified":"2022-04-04T10:51:12.422Z","1.0.1":"2021-04-26T09:37:02.803Z"},"maintainers":[{"name":"leekafai","email":"leekafai@outlook.com"}],"description":"provides a duplicate function call suppression mechanism.","homepage":"https://github.com/leekafai/singleflight#readme","repository":{"type":"git","url":"git+https://github.com/leekafai/singleflight.git"},"author":{"name":"leekafai"},"bugs":{"url":"https://github.com/leekafai/singleflight/issues"},"license":"MIT","readme":"Golang singleflight in Node\r\n---\r\n\r\nprovides a duplicate function call suppression mechanism.\r\n\r\n\r\n当在并发中需要异步获取相同的响应数据时，可以使用 `singleFlight` 减少实际发出的异步请求数量。\r\n\r\n例如在一个 HTTP 服务中的接口 `/getACombo` 中，需要返回一个缓存于 redis 的数据。\r\n\r\n当多个客户端并发请求 `/getACombo` 接口，并传递相同的参数时，期望中返回的数据是一致且可以共用的。\r\n\r\n此时，在不使用 `singleFlight` 的情况下，每一个请求都会发出一个 redis 指令；\r\n\r\n使用 `singleFlight` 后，N 个期望返回数据相同的请求，将共用一个 redis 指令执行的结果,可以大幅减少发出的 redis 指令，大大减少了 redis 的指令执行数量、网络传输量。\r\n\r\n\r\n[singleflight](https://pkg.go.dev/golang.org/x/sync/singleflight)\r\n\r\n### 安装\r\n\r\n```shell\r\nnpm i @9f/singleflight -S\r\n```\r\n\r\n### 使用案例\r\n\r\n```javascript\r\nconst singleFlight = require('@9f/singleflight')\r\nlet remoteGetRealTimes = 0 // 异步结果返回的次数\r\nlet concurrentTimes = 0 // 实际触发异步请求响应的次数\r\nconst wait = 2e3\r\n// 模拟异步请求的响应\r\nconst remote = {\r\n  get: (comboName) => {\r\n    return new Promise((resolve) => {\r\n      setTimeout(() => {\r\n        resolve({ A: ['炒饭', '冰红茶'], B: ['拉面', '奶茶'] }[comboName])\r\n        remoteGetRealTimes++ // 记录实际触发异步请求响应的次数\r\n      }, wait)\r\n    })\r\n  }\r\n}\r\n// 模拟一个异步请求\r\nconst getACombo = async (comboName) => {\r\n  const r = await remote.get(comboName)\r\n  return r\r\n}\r\n// 封装后的方法，传参方式异于原来的方法：首位传参为一个 string 的 key\r\nconst _getACombo = singleFlight(getACombo)\r\n\r\n// 模拟在一个 http 服务中，多个请求通过接口调用 service，多次触发 getACombo 的调用\r\nfor (let i = 0; i < 2e3; i++) {\r\n\r\n  // 传递一个 key 作为调用标识。相同的调用标识，代表共用响应结果。\r\n  // 有需要的话，可以在 key 之后传递参数。但相同 key 应传递相同参数，因为响应结果需要共用。\r\n  // 获取 A 套餐\r\n  _getACombo('user', 'A').then((x) => {\r\n    // 多次调用，返回相同的结果\r\n    concurrentTimes++ // 记录异步结果返回的次数\r\n    console.log(x) //  套餐内容\r\n  }).catch((e) => {\r\n    console.error(e) // 可以使用正常的错误捕捉\r\n  })\r\n\r\n}\r\nsetTimeout(() => {\r\n  console.log('并发调用 getFruitCache 次数', concurrentTimes) // 1e3\r\n  console.log('实际调用 remote.get 次数', remoteGetRealTimes) // 远小于 1e3\r\n}, wait + 200)\r\n```","readmeFilename":"readme.md"}