Using async / await inside async.auto chain leads to TypeError: callback is not a function

Using async / await inside async.auto chain leads to TypeError: callback is not a function

您使用的是哪个版本的异步?

2.6.1

问题出现在哪个环境(Node version/browser版本)

8.11.3

你做了什么?请提供一个最小的可重现案例来说明问题。

假设 fileObj 是从外部提供的:

async.auto({
  download: (downloadCB) => {
    if (fileObj) {
      fs.writeFile(__dirname + ‘fileNew.txt’, fileObj.content, 'base64', function (err) {
        if (err){
          return downloadCB(err);
        }
        return downloadCB(null , fileObj.generatedFileName); // works fine
      });
    } else {
      let err = new Error('File not found');
      return downloadCB(err);
    }
  },
  collectData: ['download', async (results, collectCB) => {
    console.log(typeof collectCB); // prints undefined
    console.log(typeof results); // prints correct object

    let res = await anHttpRequest();
    if (res.response && res.response.statusCode == 200) {
      return collectCB(null , 'fileCombined.txt'); // This is where the ISSUE happens
    }
    else if(res.response.statusCode >= 300) {
      return collectCB(new Error('Request failed inside async-auto'));
    }
  }],

  filterData: ['collectData', (results, filterCB) => {
    doFilter(results.collectData, filterCB);
  }],
})

你预计会发生什么?

collectData执行完成后,filterData应该开始执行collectCB函数内部传递的参数

实际结果如何?

类型错误:collectCB 不是函数。

相同的代码在 2.0.1 版中执行良好,但在升级到 2.6.1 后它已停止工作,这对我们来说至关重要。任何解决方法也将不胜感激。

官方复制粘贴documentation:

Wherever we accept a Node-style async function, we also directly accept an ES2017 async function. In this case, the async function will not be passed a final callback argument, and any thrown error will be used as the err argument of the implicit callback, and the return value will be used as the result value. (i.e. a rejected of the returned Promise becomes the err callback argument, and a resolved value becomes the result.)

基于 documentation(已在其他答案中引用,但再次引用)

Wherever we accept a Node-style async function, we also directly accept an ES2017 async function. In this case, the async function will not be passed a final callback argument, and any thrown error will be used as the err argument of the implicit callback, and the return value will be used as the result value. (i.e. a rejected of the returned Promise becomes the err callback argument, and a resolved value becomes the result.)

你会做的是

async.auto({
    download: (downloadCB) => {
        if (fileObj) {
            fs.writeFile(__dirname + ‘fileNew.txt’, fileObj.content, 'base64', function(err) {
                if (err) {
                    return downloadCB(err);
                }
                return downloadCB(null, fileObj.generatedFileName); // works fine
            });
        } else {
            let err = new Error('File not found');
            return downloadCB(err);
        }
    },
    //                                      Note, no callback as per documentation
    collectData: ['download', async (results) => {
        console.log(typeof results); // prints correct object

        let res = await anHttpRequest();

        if (res.response && res.response.statusCode == 200) {
            // this return is equivalent to callback(null, value);
            return 'fileCombined.txt';
        } else if (res.response.statusCode >= 300) {
            // this throw is equivalent to callback(err);
            throw new Error('Request failed inside async-auto');
        }
        // but surely something should be here!? for status code 201-209?
    }],

    filterData: ['collectData', (results, filterCB) => {
        doFilter(results.collectData, filterCB);
    }],
})