使用promises链接方法

时间:2017-11-16 12:02:06

标签: javascript promise

我正试图了解承诺,我想我可以看到它们的工作方式,你可以说Step 1Step 2然后Step 3
我使用node-fetch(使用本机Promises)

创建了此下载函数
## FileDownload.js

const fetch = require('node-fetch');
const fs = require('fs');

module.exports = function(url, target) {
  fetch(url)
    .then(function(res) {
      var dest = fs.createWriteStream(target);
      res.body.pipe(dest);
    }).then(function(){
      console.log(`File saved at ${target}`)
    }).catch(function(err){
      console.log(err)
  });
}

所以这一切都按顺序执行,我可以看到它是如何工作的。

我有另一种方法,然后将CSV文件转换为JSON(再次使用保证)

## CSVToJson.js

const csvjson = require('csvjson');
const fs = require('fs');
const write_file = require('../helpers/WriteToFile');

function csvToJson(csv_file, json_path) {
  return new Promise(function(resolve, reject) {
    fs.readFile(csv_file, function(err, data){
      if (err)
        reject(err);
      else
        var data = data.toString();
        var options = {
          delimiter : ',',
          quote     : '"'
        };
      const json_data = csvjson.toObject(data, options);
      write_file(json_path, json_data)
      resolve(data);
    });
  });
}

module.exports = {
  csvToJson: csvToJson
}

当我一个接一个地调用这些函数时,第二个函数失败,因为第一个函数没有完成。

我是否需要将这两个函数调用包含在另一个承诺中,即使它们各自都已实现了承诺?

请告知我是否完全误解了这个

1 个答案:

答案 0 :(得分:2)

  

当我一个接一个地调用这些函数时,第二个函数失败,因为第一个函数没有完成。

第一个有两个问题:

  1. 它不会等待写入文件;它只是设置管道而不等待过程完成
  2. 它没有为调用者提供任何方式来知道该过程何时完成
  3. 要处理第一个问题,您必须等待目标流上的finish事件(pipe返回)。为了处理第二个问题,你需要回复一个在这种情况发生之前不会实现的承诺。这些内容(见**评论):

    module.exports = function(url, target) {
      // ** Return the end of the chain
      return fetch(url)
        .then(function(res) {
          // ** Unfortunately, `pipe` is not Promise-enabled, so we have to resort
          // to creating a promise here
          return new Promise((resolve, reject) => {
            var dest = fs.createWriteStream(target);
            res.body.pipe(dest)
              .on('finish', () => resolve()) // ** Resolve on success
              .on('error', reject);          // ** Reject on error
          });
        }).then(result => {
          console.log(`File saved at ${target}`);
          return result;
        });
        // ** Don't `catch` here, let the caller handle it
    }
    

    然后,您可以对结果使用thencatch进行下一步:

    theFunctionAbove("/some/url", "some-target")
        .then(() = {
            // It worked, do the next thing
        })
        .catch(err => {
            // It failed
        });
    

    (或async / await。)

    旁注:我还没有对其进行代码审核,但csvToJson中的一个严重问题跳了出来,这也是一个小问题,而@Bergi突出了第二个问题:

    1. {逻辑

    2. 周围缺少}else
    3. 小问题是您有var data = data.toString();data是该函数的参数,因此var具有误导性(但无害)

    4. 它没有正确处理else回调的readFile部分代码中的错误

    5. 我们可以通过在resolve中执行else并在then处理程序中执行其余逻辑来解决这两个问题:

      function csvToJson(csv_file, json_path) {
        return new Promise(function(resolve, reject) {
          fs.readFile(csv_file, function(err, data){
            if (err)
              reject(err);
            else
              resolve(data);
          });
        })
        .then(data => {
          data = data.toString();
          var options = {
            delimiter : ',',
            quote     : '"'
          };
          const json_data = csvjson.toObject(data, options);
          write_file(json_path, json_data);
          return data;
        });
      }