[英]Use promises instead of callbacks
我已经从learningyounode完成了本练习,并且尝试使用ES2015的promises(或者更容易的话,使用其他库)来重构它。 我已经阅读了诺言,并且我想我了解了它们的工作原理,但是我想知道是否有可能在以下代码中使用它们以及如何实现它们。
我的目标是使代码更易于阅读和理解,并更好地理解过程中的承诺。
let http = require("http");
if (process.argv.length != 5) {
throw new Error("Please provide the 3 URLs as a command line arguments");
}
let urls = [];
let results = [];
let count = 0;
for (let i = 2; i < process.argv.length; i++) {
urls.push(process.argv[i]);
}
function httpGet(index) {
let url = urls[index];
let result = "";
http.get(url, res => {
res.on("data", data => {
result += data;
});
res.on('end', () => {
count += 1;
results[index] = result;
if (count === 3) {
results.forEach(function(result) {
console.log(result);
});
}
});
});
}
for (let i = 0; i < urls.length; i++) {
httpGet(i);
}
您可以尝试这样的事情:
'use strict'; const http = require('http'); if (process.argv.length != 5) { throw new Error('Please provide the 3 URLs as a command line arguments'); } let urls = []; for (let i = 2; i < process.argv.length; i++) { urls.push(process.argv[i]); } function httpGet(url) { let result = ''; return new Promise((resolve, reject) => { http.get(url, function (res) { res.on('error', err => { reject(err); }); res.on('data', data => { result += data; }); res.on('end', () => { //You can do resolve(result) if you don't need the url. resolve({url, result}); }); }) }); } let promises = urls.map(url => httpGet(url)); Promise.all(promises) .then(results => { console.log(`All done. Results: ${results}`); }) .catch(err => { console.error(err); });
你可以做这样的事情, 但您应该注意,结果可能不会按照给定输入的顺序返回。
编辑:现在将按照给定的顺序输出数据。
const http = require('http');
if (process.argv.length != 5)
throw new Error("Please provide the 3 URLs as a command line arguments");
let urls = [];
let results = [];
let count = 0;
for (let i = 2; i < process.argv.length; i++)
urls.push(process.argv[i]);
function httpGet (url)
{
return new Promise((resolve, reject) => {
let result = '';
http.get(url, res => {
res.on('data', data => result += data);
res.on('end', () => resolve(result))
}).on('err', reject);
});
}
function printResults() {
for (let result of results) {
console.log(result);
}
}
for (let i = 0; i < urls.length; i++) {
httpGet(urls[i])
.then(result => {
results[i] = result;
if (++count === 3)
printResults();
})
.catch(err => console.log(err));
}
出于教育目的,自己实现所有promise逻辑可能会很有用,但应注意,有一些带有promise支持的HTTP请求的良好模块,例如request-promise
:
每月下载量超过一百万次,它被广泛使用,并且是针对此类任务的经过测试的解决方案。 而且,我总是建议对任何实际工作都使用经过良好测试的解决方案,而不是重新发明轮子。
现在,出于教育目的,我总是建议尽可能多地重新设计轮子。 例如,有关将基于回调的代码转换为Promise的一些示例,请参见以下答案:
另请参阅此答案的所有链接:
您会发现同时使用回调和Promise的许多相同代码的示例,以便您可以检查差异。
Node核心库的接口不是基于承诺的。 但是,您可以使用简单的函数将接受Node样式回调的函数转换为返回promise的函数。 自己编写可能是一个很好的练习。 或者在npm上找到它。 此转换函数通常称为promisify
。 它的更高级版本采用一个对象并转换其所有方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.