【问题标题】:How to count callbacks?如何计算回调?
【发布时间】:2022-02-01 14:36:45
【问题描述】:

我尝试从 3 个来源收集数据,但这些都是异步的。因此我试图计算回调。这是我为此目的编写的代码。

var http = require('http');
var data_str1 = '';
var data_str2 = '';
var data_str3 = '';
var ended = 0;
function callback1(response){
    response.on('end', function(){ended++;});
    response.on('data', function(data){
        data_str1 += data;
    });
}

function callback2(response){
    response.on('end', function(){ended++;});
    response.on('data', function(data){
        data_str2 += data;
    });
}

function callback3(response){
    response.on('end', function(){ended++;});
    response.on('data', function(data){
        data_str3 += data;
    });
}

http.get(process.argv[2], function(response){
    callback1(response);
    if (ended == 3) console.log(data_str1);
});

http.get(process.argv[3], function(response){
    callback2(response);
    if (ended == 3) console.log(data_str2);
});

http.get(process.argv[4], function(response){
    callback3(response);
    if (ended == 3) console.log(data_str3);
});

你能告诉我这段代码有什么问题吗?

【问题讨论】:

  • 你想达到什么目的?为什么不能使用异步库或承诺?
  • @Andrius 我是 nodejs 的新手,我正在尝试解决 learnyounode 的问题。问题想在没有任何库的情况下解决。

标签: node.js asynccallback


【解决方案1】:

这是我的解决方案。我已经测试过了。

var http = require('http');
var concat = require('concat-stream');

var urls = [];
var responses = [];
var count = 0;

for (var i = 2; i < process.argv.length; i++) {
  urls.push(process.argv[i]);
}

function readResponse(index) {
  http.get(urls[index], function(response) {
    response.pipe(concat(function(data) {
      responses[index] = data.toString();
      count++;

      if (count == 3) {
        responses.forEach(function(response) {console.log(response);});
      }
    }));
  });
}

for (var i = 0; i < urls.length; i++) {
  readResponse(i);
}

【讨论】:

    【解决方案2】:
    const http = require('http');
    const bl = require('bl');
    const results = [];
    let count = 0;
    function printResults () {
      for (let i = 0; i < 3; i++) {
        console.log(results[i])
      }
    }
    
    function httpGet (index) {
      http.get(process.argv[2 + index], function (response) {
        response.pipe(bl(function (err, data) {
          if (err) {
            return console.error(err)
          }
    
          results[index] = data.toString()
          count++
    
          if (count === 3) {
            printResults()
          }
        }))
      })
    }
    
    for (let i = 0; i < 3; i++) {
      httpGet(i)
    }
    

    【讨论】:

      【解决方案3】:

      这里的问题是 if (ended == 3) console.log(data_str2); 将在callback2(response); 之后运行 它不等待response.on('end', function(){ended++;});

      【讨论】:

        【解决方案4】:

        我的解决方案,简单直接

        const http = require('http')
        const bl = require('bl')
        const results = []
        let count = 0
        
        function printResults () {
          for (let i = 0; i < 3; i++) {
            console.log(results[i])
          }
        }
        
        function httpGet (index) {
          http.get(process.argv[2 + index], function (response) {
            response.pipe(bl(function (err, data) {
              if (err) {
                return console.error(err)
              }
        
              results[index] = data.toString()
              count++
        
              if (count === 3) {
                printResults()
              }
            }))
          })
        }
        
        for (let i = 0; i < 3; i++) {
          httpGet(i)
        }
        

        【讨论】:

          【解决方案5】:

          在您的代码中检查回调函数中的结束值 (ended===3)。我使用类似的方法解决了这个问题。请注意,我对所有三个 url 都使用了一个回调函数

          const http = require("http");
          
          let url1 = process.argv[2];
          let url2 = process.argv[3];
          let url3 = process.argv[4];
          let str1 = "";
          let str2 = "";
          let str3 = "";
          let end = 0;
          
          function cb(response, str) {
            response.on("data", data => {
              if (str === "str1") str1 += data;
              if (str === "str2") str2 += data;
              if (str === "str3") str3 += data;
            });
            response.on("end", () => {
              end++;
              if (end === 3) {
                console.log(`${str1}\n${str2}\n${str3}`);
              }
            });
          }
          
          http.get(url1, response => {
            cb(response, "str1");
          });
          
          http.get(url2, response => {
            cb(response, "str2");
          });
          
          http.get(url3, response => {
            cb(response, "str3");
          });
          

          【讨论】:

            【解决方案6】:

            我的工作解决方案代码更少:

            const http = require('http')
            
            const [, , URL_1, URL_2, URL_3] = process.argv
            
            const printData = (URL, cb) =>
                () => http.get(URL, res => {
                    let data = ''
                    res.on('data', chunk => data += chunk.toString())
                    res.on('end', () => {
                        console.log(data)
                        cb()
                    })
                })
            
            printData(URL_1, printData(URL_2, printData(URL_3, null)))()
            

            【讨论】:

            • 您的答案可以通过添加有关代码的作用以及它如何帮助 OP 的更多信息来改进。
            • 我会把我的评论留给现在可能会读到这篇文章的人。从 Node.js 的角度来看,您的答案不是很好。原因是您在这里没有使用异步电源。您只需一个接一个地调用所有 3 个 URL,但前提是前者将从 GET 读取所有数据。这不是 OP 所要求的。他询问了“如何计算回调”,它用于与 Node.js 一起以异步方式工作。
            【解决方案7】:

            我知道这是一个老问题,但我只是想用不同的方法分享我的丑陋解决方案。

            const http = require('http');
            
            let data1 = '';
            let data2 = '';
            let data3 = '';
            
            http.get(process.argv[2], (res) => {
                res.on('data', (data) => {
                    data1 += data;
                })
                res.on('end', () => {
                    http.get(process.argv[3], (res) => {
                        res.on('data', (data) => {
                            data2 += data;
                        })
                        res.on('end', () => {
                            http.get(process.argv[4], (res) => {
                                res.on('data', (data) => {
                                    data3 += data;
                                })
                                res.on('end', () => {
                                    console.log(data1); console.log(data2); console.log(data3);
                                })
                            })
                        })
                    })
                })
            })
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-07-15
              • 1970-01-01
              • 1970-01-01
              • 2019-05-24
              • 2011-06-25
              • 2021-06-04
              相关资源
              最近更新 更多