这是在 Express 4.0 中进行 API 调用的最佳做法吗

Is this a best practice to make API call in Express 4.0

应用程序正在向服务器发出 API 请求并 return 返回收到的响应。这里想了解一下

(i) 调用 API 并从服务器接收响应是否正确。

(ii) if return 语句传回值是正确的方式

该模块被称为

str = apiRequest(search, lang);

模块是

var https = require('https');

function apiRequest(search, lang) {

   var options = {
       host: 'localhost:8080',
       path: '/api?search=' + search + '&lang=' + lang
   };


   function resData(res) {
       console.log("Status Code : ", res.statusCode);

       var str = '';

       res.on('data', function (chunk) {
           str += chunk;
       });

       res.on('end', function () {
           return JSON.parse(str);   // Is this a right way to return data
       });

       res.on('error', function(e) {
           console.error(e);
       });
   }

   https.get(options, resData).end();
};

不,这行不通。我将在下面评论相关部分。

而不是在 apiRequest 中有这个:

function apiRequest(search, lang) {
   function resData(res) {
       // ...
       res.on('end', function () {
           return JSON.parse(str);   // Is this a right way to return data
       });
       // ...
   }
   https.get(options, resData).end();
}

并调用它:

str = apiRequest(search, lang);

您应该传递 回调 或 return 一个 promise.

使用回调

你的 apiRequest 函数可以接受一个额外的参数,一个回调:

function apiRequest(search, lang, callback) {
   function resData(res) {
       // ...
       res.on('end', function () {
           callback(null, JSON.parse(str));
       });
       res.on('error', function(e) {
           console.error(e);
           callback(e);
       });
       // ...
   }
   https.get(options, resData).end();
}

现在您可以将其用作:

apiRequest(search, lang, function (error, str) {
    if (err) {
        // you have error
    } else {
        // you have your str here
    }
});

使用承诺

你的apiRequest函数可以return一个承诺:

function apiRequest(search, lang, callback) {
   return new Promise(function (resolve, reject) {
     function resData(res) {
       // ...
       res.on('end', function () {
           resolve(JSON.parse(str));
       });
       res.on('error', function(e) {
           console.error(e);
           reject(e);
       });
       // ...
     }
     https.get(options, resData).end();
   }
}

现在您可以将其用作:

apiRequest(search, lang)
.then(function (str) {
    // you have your str here
})
.catch(function (err) {
    // you have error
});

这没有经过测试,所以可能会有一些小错误,但这是一般的想法。当我发现一些错误时,我会更新答案。

总结

总而言之,您可以使用两种样式来编写这样的异步函数:回调或承诺。您将无法仅 return 数据,因为 return 从根本上讲是同步的 - 您必须立即对 return 进行处理 - 除非您 return 是一个承诺可以稍后解决或拒绝。

正在解析JSON

还应该记住的是,您应该始终在 try {} catch {} block 中 运行 JSON.parse() 来处理不正确的 JSON 错误,否则整个应用程序可能会崩溃。 JSON.parse() 对错误输入抛出异常。有关详细信息,请参阅 this answer

这会使您的代码更加复杂,但您可以避免这种复杂化,并通过使用 request 模块使其变得更加简单 - 请参阅下面的更新。

更简单的示例

回调

要有一个更简单的工作示例并且您不必手动解析 JSON,请考虑我刚刚根据您的示例编写的代码,但调用 GitHub API 所以它可以被每个人测试 - 它打印某人的网站给定他的 GitHub 昵称但在其他方面与你的代码类似:

'use strict';
var request = require('request');

function apiRequest(search, callback) {

  var options = {
    url: 'https://api.github.com/users/' + search,
    json: true,
    headers: {'User-Agent': 'request'}
  };

  function resData(err, res, data) {
    if (err) {
      callback(err);
    } else if (res.statusCode !== 200) {
      callback(res.statusCode);
    } else {
      // data is already parsed as JSON:
      callback(null, data.blog);
    }
  }

  request.get(options, resData);

}

apiRequest('rsp', function (err, data) {
  if (err) {
    console.log('Error:', err);
  } else {
    console.log('Data:', data);
  }
});

这是一个使用回调的示例。

承诺

下面是一个使用 promises 的例子:

'use strict';
var request = require('request');

function apiRequest(search, callback) {

  return new Promise(function (resolve, reject) {

    var options = {
      url: 'https://api.github.com/users/' + search,
      json: true,
      headers: {'User-Agent': 'request'}
    };

    function resData(err, res, data) {
      if (err) {
        reject(err);
      } else if (res.statusCode !== 200) {
        reject(res.statusCode);
      } else {
        // data is already parsed as JSON:
        resolve(data.blog);
      }
    }

    request.get(options, resData);

  });

}

apiRequest('rsp')
  .then(function (data) {
    console.log('Data:', data);
  })
  .catch(function (err) {
    console.log('Error:', err);
  });

简化

可以通过使用粗箭头函数、匿名函数和对象字面量进一步简化:

'use strict';
var request = require('request');

function apiRequest(search, callback) {

  return new Promise((resolve, reject) => {
    request.get({
      url: 'https://api.github.com/users/' + search,
      json: true,
      headers: {'User-Agent': 'request'}
    }, (err, res, data) => {
      if (err) {
        reject(err);
      } else if (res.statusCode !== 200) {
        reject(res.statusCode);
      } else {
        resolve(data.blog);
      }
    });
  });

}

apiRequest('rsp')
  .then(data => console.log('Data:', data))
  .catch(err => console.log('Error:', err));

更多信息

你可以看到一些其他答案,我在其中更详细地解释了回调和承诺之间的区别以及如何一起使用它们,这可能会对你有所帮助:

  • An explanation of what a promise really is, on the example of AJAX requests
  • An explanation on how to handle errors in callbacks and promises