Понимание функций (err, data) обратных вызовов

javascript node.js asynchronous callback

12117 просмотра

4 ответа

Поэтому я не понимаю, как работает обратный вызов функции (err, data), всегда ли первый аргумент является обработчиком ошибок?

Как насчет оставшихся аргументов, если у вас есть что-то вроде функции (x, y, z, a, b, c)?

Как данные из fs.readFile передаются из верхней строки кода в нижнюю строку кода? Или, другими словами, как вывод fs.readFile помещается в аргумент данных?

fs.readFile(pathToFile, function (err, **data**) {
    bufferString = **data**.toString();

Я мог бы заменить функцию (err, data) на функцию (x, y) и функцию (x, y, z, a, b, c)

Но работает только второй аргумент (data и y), это только синтаксис обратных вызовов javascript?

Например, это рабочий код для асинхронного чтения файла и распечатки количества строк в файле:

var fs = require('fs');
var pathToFile = process.argv[2];
var bufferString, bufferStringSplit;

function counter(callback) {
  fs.readFile(pathToFile, function (err, data) {
    bufferString = data.toString();
    bufferStringSplit = bufferString.split('\n');
    callback();
  });
}

function logMyNumber() {
  console.log(bufferStringSplit.length-1);
}

counter(logMyNumber);
Автор: enducat Источник Размещён: 12.11.2019 09:48

Ответы (4)


4 плюса

Вызывающая сторона обратного вызова (который readFileв данном случае является методом) решает, какие аргументы передаются обратному вызову. Вы должны объявить свой обратный вызов так, чтобы он соответствовал тому, что readFileговорит, что он будет передан обратному вызову. Вы можете называть аргументы как угодно (имена, которые вы используете, не имеют значения), но они получат значения в порядке, который readFileрешает.

В этом случае fs.readFile()вызывает обратный вызов с двумя аргументами, которые есть в вашем коде, как в callback(err, data).

Вот пример из документа node.js:

fs.readFile('/etc/passwd', function (err, data) {
  if (err) throw err;
  console.log(data);
});
Автор: jfriend00 Размещён: 18.12.2013 01:08

2 плюса

Это легко понять на примере ... вы можете написать свою собственную версию функции, которая использует обратный вызов, довольно просто:

function getTwoStringsAsync(callback) {
    setTimeout(function() {
        callback("foo", "bar");
    }, 1000);
}

Здесь функция getTwoStringsAsyncпредварительно предполагает, что «обратный вызов» является функцией, и это подразумевает сигнатуру (два параметра, которые являются строками). Потребитель вашего метода может придерживаться подразумеваемой подписи или нет. Он может использовать одно или оба из этих значений, или ни одно. Но если он принимает более двух параметров, они будут отображаться как неопределенные.

getTwoStringsAsync(function() { console.log("done!"); });
getTwoStringsAsync(function(first, second) { console.log("got " + first + ", " + second); });
getTwoStringsAsync(function(first, second, third) { console.log(third); });   // "undefined"

Возможно, это ограничение, или сильная сторона, или языки со слабой типизацией, такие как Javascript, в том, что сигнатуры функций не будут проверяться. Строго типизированный язык может генерировать ошибку или предупреждение компилятора при первом или третьем использовании выше.

Автор: McGarnagle Размещён: 18.12.2013 01:12

1 плюс

Аргументы обратного вызова зависят от того, как вызывается обратный вызов. Например:

var map = function(xs, f) {
  var result = [];
  for (var i=0; i<xs.length; i++) {
    // Here we call the callback function
    // with the element as context, the element as first param
    // and the index as second param.
    // Extra parameters are `undefined`
    result.push(f.call(xs[i], xs[i], i));
  }
  return result;
};

Тогда вы бы использовали это как:

var addIdx = function(x,i){ return x+i };
map([1,2,3], addIdx); //=> [1,3,5]
Автор: elclanrs Размещён: 18.12.2013 01:10

0 плюса

Когда вы вызываете функцию, она может либо вернуть одно значение, либо выдать единственную ошибку.

Итак, «эквивалент» этого синхронного кода:

try {
    var data = functionCall();
    //Use data
}
catch(err) {
    console.log(err);
}

Это асинхронный обратный вызов:

functionCallAsync(function(err, data) {
    if (err) {
         console.log(err);
    }
    else {
         //Use data
    }

});

Теперь вы можете понять, почему нет смысла использовать несколько значений в обратном вызове. На самом деле такая картина активно вредна.

Например, при использовании генераторов вы вернетесь к возможности использовать только одно возвращаемое значение. Но если бы какой-нибудь неосведомленный автор библиотеки пошел дальше и нарушил соглашение об обратном вызове и использовал несколько, это было бы невозможно.

async(function* () {
    try {
        //What if `functionCallAsync` was called back with multiple values?
        var data = yield functionCallAsync();
        //Use data
    }
    catch(e) {
        console.log(e);
    }
});
Автор: Esailija Размещён: 19.12.2013 11:07
Вопросы из категории :
32x32