回调函数中的参数列表是规定好的么???(java 过来的 ,是不是我有什么思维定势)
发布于 7 年前 作者 TianYongwei 4971 次浏览 来自 问答

1.自己写的测试中使用了 fs模块的readFile方法。想知道这个方法的回调为社么这么写? 为什么第一个参数是err,第二个参数是data. 在这个回调中竟然很神奇的拿到了数据

var fs = require("fs");

fs.readFile('input.txt', function (err, data) {
   if (err){
      console.log(err.stack);
      return;
   }
   console.log(data.toString());
});
console.log("程序执行完毕");

2.然后我就想看看 这个回调是怎么拿到err 和data 的数据的,找到了源码

fs.readFile = function(path, options, callback_) {
  var callback = maybeCallback(arguments[arguments.length - 1]);

  if (!options || typeof options === 'function') {
    options = { encoding: null, flag: 'r' };
  } else if (typeof options === 'string') {
    options = { encoding: options, flag: 'r' };
  } else if (typeof options !== 'object') {
    throwOptionsError(options);
  }

  var encoding = options.encoding;
  assertEncoding(encoding);

  var flag = options.flag || 'r';

  if (!nullCheck(path, callback))
    return;

  var context = new ReadFileContext(callback, encoding);
  var req = new FSReqWrap();
  req.context = context;
  req.oncomplete = readFileAfterOpen;

  binding.open(pathModule._makeLong(path),
               stringToFlags(flag),
               0o666,
               req);
};



function nullCheck(path, callback) {
  if (('' + path).indexOf('\u0000') !== -1) {
    var er = new Error('Path must be a string without null bytes.');
    er.code = 'ENOENT';
    if (typeof callback !== 'function')
      throw er;
    process.nextTick(callback, er);
    return false;
  }
  return true;
}


function ReadFileContext(callback, encoding) {
  this.fd = undefined;
  this.size = undefined;
  this.callback = callback;
  this.buffers = null;
  this.buffer = null;
  this.pos = 0;
  this.encoding = encoding;
  this.err = null;
}

可是源码里里面没有说啊 ,这到底是怎么回事? 谢谢

14 回复

约定好的?有相关的说法吗

http://fredkschott.com/post/2014/03/understanding-error-first-callbacks-in-node-js/

这跟nodejs的实现有关么?

来自酷炫的 CNodeMD

回调函数中的参数列表是规定好的,一般以错误(err)优先。关于回调的问题,举个简单的例子。 比如说我有一个函数fun1,需要两个参数,第一个参数是一个数字,第二个参数是一个函数。

function fun1(num,callback){
	var str = "您输入的数字是" + num;
	//在合适的时候执行回调函数,此时,我们会给回调函数一些参数,注意你此时输入的参数顺序。
	callback(null,str);
}
//我们执行fun1
fun1(10,function(err,result){
	//因为方法比较简单,并不发生错误,只是举例
	console.log(err,result);	
});

如你所见,你回调的时候(调用callback)录入的参数顺序,就是fun1中你传递函数中的参数顺序。fs.readFile方法也一样,你传入你的函数之后,他会调用你的回调函数,并按照一定的顺序输出你需要的值,具体顺序可以查看api。

约定大于配置

回调的约定是: 2个参数 function (err, data)

@youthfighter 你好,谢谢你的回答。 你这里举得这个例子我很明白。我在调用fun1的时候看了fun1函数是怎么定义的,自然就能知道回调函数怎么写,最起码我知道有几个参数,还能知道第二个参数的意义,就是我想要的额内容。但是我并不能知道fs.readFile()这个函数的回调有个参数,以及参数的具体意义,因为readFile 在声明的时候并没有想你的fun1函数中的callback(null,str)类似的语句啊。 可能是我看的不够仔细?

@alsotang 谢谢你的回答。 顺便问一下 这个约定能能在源码里面找到证据吗?

你能举个例子来说明问题吗? 谢谢。

@htoooth 谢谢你的回答。 那也就是说,我写回调的时候参数列表一定是这两个吗?还是只有这些node比较基础的模块才会是这样?

这样理解也不对好像,你能在讲下你的理解吗?谢谢。

@TianYongwei 所以你得看api啊,就像你引用一个jar,使用第三方的类,调用第三方的方法public void fun1(a,b,c,d){},你也不能知道a是啥不是?只能查api。 fs.readFile可以查node的rs模块的api。回调函数的参数有这样的描述“回调函数传递了两个参数 (err, data), data 就是文件的内容。”以下是node的api地址,你可以看一下http://nodeapi.ucdok.com/#/api/fs.html。

@TianYongwei 不一定,回调函数的参数没有规定必须有几个,看你的需求。使用第三方模块的话,回调函数有几个参数,得看api。

@youthfighter 嗯,谢谢。看到了。 xxxx11.png

api 上说的很清楚。这么说来看源码反而是有点扰乱思路了。因为源码并不能看懂多少[笑哭]。

我顺带着看了其他的api, 确实对callback的参数列表都有说明。

(跟看java的api不同的是,java只需要看readFile的参数列表,node的api你还要看看回调函数的参数列表,readFile的参数列表和readFile回调函数的参数列表你都知道的时候才能开始写程序。)

Thank you all.

@TianYongwei nodejs所有的官方api都这个形式的,源码的证据我没找过

@TianYongwei 这是个公认的约定吧,这样写,大家都会处理正确的处理异常;和java的throws catch throw区别略大的

  1. 看API文档。
  2. 看源码。

来自酷炫的 CNodeMD

回到顶部