代码之家  ›  专栏  ›  技术社区  ›  yozawiratama

Javascript如何更好地编写嵌套回调代码?

  •  4
  • yozawiratama  · 技术社区  · 7 年前

    我有三层回调,如下所示:

        app.post('/', (req, res) => {
            var filename = `outputs/${Date.now()}_output.json`;
            let trainInput = req.files.trainInput;
            let trainOutput = req.files.trainInput;
            let testInput = req.files.trainInput;
    
            //first
            trainInput.mv(`inputs/${req.body.caseName}/train_input.csv`, function (err) {
                if (err) return res.status(500).send(err);
                //second
                trainOutput.mv(`inputs/${req.body.caseName}/train_output.csv`, function (err) {
                    if (err) return res.status(500).send(err);
                    //third
                    testInput.mv(`inputs/${req.body.caseName}/test_input.csv`, function (err) {
                        if (err) return res.status(500).send(err);
    
                        res.send('success');
                    });
                });
            });   
        });
    

    在这种情况下,只有3个文件上传。在另一个例子中,我有超过10个文件上传,它进行10层回调。我知道这是因为JavaScript异步。

    有没有办法,在这种情况下,使一个美丽的代码?这是因为当它10层回调时,代码在水平方向上看起来很奇怪。

    3 回复  |  直到 7 年前
        1
  •  6
  •   Andrew Rayan    7 年前

    app.post('/', async (req, res) => {
        var filename = `outputs/${Date.now()}_output.json`;
        let trainInput = req.files.trainInput;
        let trainOutput = req.files.trainInput;
        let testInput = req.files.trainInput;
        try {
            var result1 = await trainInput.mv(`inputs/${req.body.caseName}/train_input.csv`);
            var result2 = await trainInput.mv(`inputs/${req.body.caseName}/train_output.csv`);
            var result2 = await testInput.mv(`inputs/${req.body.caseName}/test_input.csv`);
            res.send('success');
        }
        catch (error) {
            res.status(500).send(error);
        }
    });
    
        2
  •  3
  •   Oscar R    7 年前

    你可以让函数返回一个承诺

    我建议做一个函数,因为你做同样的事情3次。在本例中,我调用了函数“save”,但您可以随意调用它。第一个参数是文件结尾,第二个参数是输出文件名。

    function save(file, output) = return new Promise((resolve, reject) => {
      file.mv(`inputs/${req.body.caseName}/${output}`, err => 
      if (err) return reject(err)
      resolve()
    })
    
    Promise.all([
        save(req.files.trainInput, 'train_input.csv'),
        save(req.files.trainInput, 'train_output.csv'),
        save(req.files.trainInput, 'test_input.csv')
    ])
    .then(_ => res.send(200))
    .catch(err => res.send(400);
        3
  •  0
  •   Dennis O'Keeffe    7 年前

    您使用什么版本的节点?如果async/await可用,则会清理一堆。

    const moveCsv = (file, dest) => {
        return new Promise((resolve, reject) => {
            //third
            file.mv(dest, function (err) {
                if (err) reject(err);
                resolve();
            });
        })
    }
    
    app.post('/', async(req, res) => {
        try {
            var filename = `outputs/${Date.now()}_output.json`;
    
            const {
                trainInput,
                trainOutput,
                testInput
            } = req.files;
    
            const prefix = `inputs/${req.body.caseName}`;
            await moveCsv(trainInput, `${prefix}/train_input.csv`);
            await moveCsv(trainOutput, `${prefix}/train_output.csv`);
            await moveCsv(testInput, `${prefix}/test_input.csv`);
            res.send('success');
        } catch(err) {
            res.status(500).send(err);
        }
    });
    

    我也假设你 trainInput trainOutput , testOutput 不是命中注定的 req.files.trainInput .

    await 调用是线程阻塞。如果writer函数需要很长时间,那么您也可以考虑将这些调用放到一个工作线程上。如果您对该服务器端点的请求是快速且不频繁的,这并不重要。

        4
  •  0
  •   Krzysztof Raciniewski Eliseo    7 年前

    你可以添加 RXJS公司 你的项目和使用

    可观测解( assuming that trainInput.mv() returns Observable ):

    /* Without a selector */
    var source = Rx.Observable.forkJoin(
      trainInput.mv(`inputs/${req.body.caseName}/train_input.csv`),
      trainInput.mv(`inputs/${req.body.caseName}/train_output.csv`),
      trainInput.mv(`inputs/${req.body.caseName}/test_input.csv`)
    );
    
    var subscription = source.subscribe(
      function (x) {
        // On success callback
        console.log('Success: %s', x);
      },
      function (err) {
        // Error callback
        console.log('Error');
      },
      function () {
        // Completed - runs always
        console.log('Completed');
      });
    
    // => Success: [result_1, result_2, result_3] or Error
    // => Completed
    
    推荐文章