2

nodejs/expressjs中的多个函数如何运行?在 php 中,它很简单,一个接一个地调用一个函数,但是节点中的这个回调业务令人困惑,我不断收到未定义变量等错误。这是我正在做的事情的基本想法。

var express = require('express');
var request = require('request');

var app = express();

app.get('/user/:id', function(req, res) {
   var id = req.params.id;

   getInformation(id, function(info) {
      res.send(info);
   });
});

app.listen(3000);

getInformation(id, callback) {
   var qty = makeExternalApiCall();
   var color = secondFunction(id);
   callback({quantity: qty, color: color});
}

makeExternalApiCall() {
   request({uri: 'https://provider.com/api/stuff/'}, function(error, response, body) {
      if (!error && response.statusCode == 200) {
         return body.qty;
      }
   }
}

secondFunction(id) {
   //look up color by id
   var color = "blue";
   return color;
}
4

2 回答 2

4

运行多个函数类似于在 PHP 中运行,除非它涉及异步函数。异步回调是可以随时调用的函数,不会与return关键字一起使用。以这个回调为例:

var cb = function(arg) {
  console.log(arg);
};

我们可以将此回调函数传递给另一个函数,并从内部调用该函数cb()

function call(text, callback) {
  callback(text);
};

var txt = 'a string';
call(txt, cb);
console.log('breakpoint');

上面的例子是同步运行的。因此执行顺序为:

call() -> cb()
console.log()

但是如果我们延迟函数或添加一个计时器(process.nextTick等到函数的调用堆栈为空,然后执行已排队的内容):

function call(text, callback) {
  process.nextTick(function() {
    callback(text);
  });
};

再次运行它,我们得到一个不同的执行顺序,因为cb()在调用栈为空之后排队运行(运行之后console.log(),它是空的):

call()
console.log()
-> cb()

大多数未定义的变量错误是由在设置之前访问变量引起的。以异步函数为例foo()

var data;

foo(function(bar) {
  data = bar;
});
console.log(data);

回调function(bar) { ... });可能在 之后被调用console.log(),这意味着console.log()运行之前data被赋予了一个值。


至于您的具体问题,请求模块是异步的并使用回调,因此您不能使用 HTTP 请求中的返回值。要从回调函数中获取结果值,您需要将其传递给另一个回调。使用return关键字只会停止函数的执行。所以改变这个:

var options = {
  uri: 'https://provider.com/api/stuff/'
};

function makeExternalApiCall() {
  request(options, function(err, res, body) {
    if (!err && res.statusCode == 200) {
       return body.qty;
    }
  }
};

要使用回调:

function makeExternalApiCall(callback) {
  request(options, function(err, res, body) {
    if (!err && res.statusCode == 200) {
       callback(null, body.qty);
    }
  }
};

然后将像这样使用该函数:

makeExternalApiCall(function(err, qty) {
  // here is qty
});

所以你的路由代码可能看起来像这样,使用嵌套回调:

function getInformation(id, callback) {
  var color = secondFunction(id);
  makeExternalApiCall(function(err, qty) {
    callback({ quantity: qty, color: color });
  });
};

app.get('/user/:id', function(req, res) {
   var id = req.params.id;

   getInformation(id, function(info) {
      res.send(info);
   });
});
于 2013-10-29T22:56:56.503 回答
0

您还可以使用 next() 函数,这使您可以在路由文件或路由文件之间实现模块化。

即使您不必担心异步和同步环境。

在回调中执行 next() ,它将仅在回调完成或执行回调时满足条件后执行。

https://expressjs.com/en/guide/using-middleware.html

于 2018-05-24T18:10:40.990 回答