使用Function.prototype.bind()

时间:2017-10-18 12:32:20

标签: javascript node.js design-patterns

我正在阅读一本关于节点设计模式的书,这是第99页here中的一些代码:

function download(url, filename, callback) { 
  console.log(`Downloading ${url}`); 
  let body; 

  async.series([ 
    callback => {                                    //[1] 
      request(url, (err, response, resBody) => { 
        if(err) { 
          return callback(err); 
        } 
        body = resBody; 
        callback(); 
      }); 
    }, 

    mkdirp.bind(null, path.dirname(filename)),       //[2] 

    callback => {                                    //[3] 
      fs.writeFile(filename, body, callback); 
    } 
  ], err => {                                        //[4] 
    if(err) { 
      return callback(err); 
    } 
    console.log(`Downloaded and saved: ${url}`); 
    callback(null, body); 
  }); 
} 

我没有关注//[2]发生的事情。书中说你正在使用bind部分应用这个功能。根据我对mdn here的理解,当你使用bind时,你不会调用该函数。

如果您稍后不致电mkdirp(),此代码如何运作?它是否与callback中的fs.writeFile参数一起引用?

我有一个潜在的解决方案。您将async.series一个函数列表交给它并执行。 mozilla mdn表示bind返回一个准备执行的函数。如果您使用callapply,您将获得该功能的结果。 async.series希望执行一个函数,这样你就可以使用bind让它在没有运行的情况下准备就绪。

1 个答案:

答案 0 :(得分:2)

你误读了代码。 mkdirp.bind(...在代码中的任何位置都没有被调用,但在async.series调用内部,更确切地说是在其参数声明(数组[])内。 async.series将包含函数引用的数组作为参数,并按顺序调用它们,一个接一个地调用它们。

  1. //[1]被调用,
  2. 然后调用//[2],这是对已经与参数绑定的mkdirp的引用(您可以看到示例here
  3. 依旧......
  4. 为了让你更清楚,代码可以用这种方式编写:

    function download(url, filename, callback) {
      console.log(`Downloading ${url}`);
      let body,
        getFile = callback => {
          request(url, (err, response, resBody) => {
            if (err) {
              return callback(err);
            }
            body = resBody;
            callback();
          });
        },
        boundMkdirp = mkdirp.bind(null, path.dirname(filename)),
        writeFile = callback => {
          fs.writeFile(filename, body, callback);
        };
    
      async.series([
        getFile,
        boundMkdirp,
        writeFile
      ], err => {
        if (err) {
          return callback(err);
        }
        console.log(`Downloaded and saved: ${url}`);
        callback(null, body);
      });
    }