简体   繁体   English

使用promise的链接方法

[英]Chaining methods using promises

I'm trying to get my head around promises, I think I can see how they work in the way that you can say do Step 1 , Step 2 and then Step 3 for example. 我正在努力兑现承诺,我想我可以看到它们的工作方式,例如您可以说先执行Step 1Step 2然后再执行Step 3
I have created this download function using node-fetch (which uses native Promises) 我已经使用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)
  });
}

So this all executes in order and I can see how that works. 所以这一切按顺序执行,我可以看到它是如何工作的。

I have another method that then converts a CSV file to JSON (again using a promise) 我有另一种方法,然后将CSV文件转换为JSON(再次使用Promise)

## 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
}

When I call these functions one after another the second function fails as the first has not completed. 当我一个接一个地调用这些功能时,第二个功能失败,因为第一个功能尚未完成。

Do I need to wrap these two function calls inside another promise, even though on their own they each have promises implemented? 我是否需要将这两个函数调用包装在另一个promise中,即使它们各自实现了promise?

Please advise if I am totally misunderstanding this 请告知我是否完全误解了

When I call these functions one after another the second function fails as the first has not completed. 当我一个接一个地调用这些功能时,第二个功能失败,因为第一个功能尚未完成。

There are two issues with the first: 第一个有两个问题:

  1. It doesn't wait for the file to be written; 它不等待文件被写入;而是等待文件写入。 all it does is set up the pipe, without waiting for the process to complete 它要做的就是设置管道,而无需等待过程完成
  2. It doesn't provide any way for the caller to know when the process is complete 它没有提供任何方式让调用者知道过程何时完成

To deal with the first issue, you have to wait for the finish event on the destination stream (which pipe returns). 要处理第一个问题,您必须等待目标流( pipe返回)上的finish事件。 To deal with the second, you need to return a promise that won't be fulfilled until that happens. 要处理第二个问题,您需要返回一个承诺,直到这种情况发生,该承诺才能兑现。 Something along these lines (see ** comments): 遵循以下原则(请参见**评论):

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
}

Then you can use then and catch on the result to proceeed to the next step: 然后,您可以使用thencatch结果以继续进行下一步:

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

(Or async / await .) (或async / await 。)


Side note: I haven't code-reviewed it, but a serious issue in csvToJson jumped out, a minor issue as well, and @Bergi has highlighted a second one: 旁注:我尚未对其进行代码审查,但csvToJson一个严重问题跳了出来,也是一个小问题,@ Bergi突出了第二个问题:

  1. It's missing { and } around the else logic else逻辑中缺少{}

  2. The minor issue is that you have var data = data.toString(); 小问题是您有var data = data.toString(); but data was a parameter of that function, so the var is misleading (but harmless) 但是data是该函数的参数,因此var具有误导性(但无害)

  3. It doesn't properly handle errors in the part of the code in the else part of the readFile callback 它无法正确处理readFile回调的else部分中的部分代码错误

We can fix both by doing a resolve in the else and performing the rest of the logic in a then handler: 我们可以通过在else进行resolve并在then处理程序中执行其余逻辑来解决这两个resolve

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;
  });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM