Promises 和 nodejs 的具体示例(没有解决方案)
concrete example for Promises and nodejs (and no solution)
所以我想通过尝试使用 nodejs 实现一个常见的用例来了解更多关于 Promises 的信息(我随意选择了 Bluebird,尽管有 'succinct' 文档):
我在一个文件中有大约 9000 个左右的 URL,还有一些空行。我愿意:
- 过滤掉空行(url.length <= 0)
- 过滤掉那些不再响应的(通过使用
request
模块的 HEAD 请求)
- MAP 通过
dns.resolve()
获取 IPv4 地址
- MAP 使用该 IPv4 地址和 http://ipinfo.io/xx.xx.xx.xx/geo 获取地理数据(好的,是的,每天有 API 限制,但假设我可以)
- 将结果信息作为JSONobjects的数组写入新文件
- 当然,这将 运行 并行进行,因此比顺序进行要快得多
第一个过滤器很简单,因为它会立即返回(这里使用 Bluebird):
Promise.each(urls, function(value, index, length) {
return value.length > 0;
}).then(
console.log(urls);
);
但是如何将异步head请求的结果反馈给Promise呢?这是我撞墙的另一个更完整的示例(请参阅内联评论):
<pre class="prettyprint lang-js">
var Promise = require('bluebird'),
request = Promise.promisifyAll(require('request'));
var urls = ["", "https://google.com/", "http://www.nonexistent.url"];
var checkLength = function(url) {
return Promise.resolve(url.length > 0);
}
var checkHead = function(url) {
return Promise.resolve(
// ??? seee below for an 'unPromised' function that works on its own
)
}
var logit = function(value) {
console.log((urls.length - value.length) + " empty line(s)");
}
Promise
.filter(urls, checkLength)
// and here? .filter(urls, checkHead) ? I don't think this would work.
// and I haven't even look at the map functions yet, although I guess
// that once I've understood the basic filter, map should be similar.
.then(logit);
</pre>
对于 checkHead
函数,我计划修改如下:
var isURLvalid = function(url) {
request
.head(url)
.on('response', function(response) {
console.log("GOT SUCCESS: " + response);
callback(response.statusCode < 300);
})
.on('error', function(error) {
console.log("GOT ERROR: " + response);
callback(false);
})
};
虽然不想抱怨,但我仍在拼命寻找一些好的入门教程 material,它可以让不熟悉 Promises 的开发人员亲身体验并展示常见用例的实际实现,cookbook-like.如果有的话,我很乐意得到一些指点。
过滤器和映射函数的工作方式与 JavaScript 数组的默认函数相同。
我之前使用过带有承诺的请求,并且有一个专门用于此的特定模块,称为 request-promise。可能更方便。
我确实觉得 request-promise 模块很棒,可以展示 Promise 的伟大之处。
与其陷入回调地狱,每个添加的请求都会更深入,你可以用 promises 来代替
rp(login)
.then(function(body) {
return rp(profile);
})
.then(function(body) {
return rp(profile_settings);
})
.then(function(body) {
return rp(logout);
})
.catch(function(err) {
// the procedure failed
console.error(err);
});
我将你当前的代码重写为这个
var Promise = require("bluebird");
var rp = require("request-promise");
var urls = ["", "https://google.com/", "http://www.nonexistent.url"];
Promise
// checkLength
.filter(urls, function(url){return url.length > 0})
.then(function(list) {
// logit
console.log((urls.length - list.length) + " empty line(s)");
// checkHead
return Promise.filter(list, function(url) {
// using request-promise and getting full response
return rp.head({ uri: url, resolveWithFullResponse: true })
.promise().then(function(response) {
// only statusCode 200 is ok
return response.statusCode === 200;
})
.catch(function(){
// all other statuscodes incl. the
// errorcodes are considered invalid
return false;
});
})
})
.then(console.log);
所以我想通过尝试使用 nodejs 实现一个常见的用例来了解更多关于 Promises 的信息(我随意选择了 Bluebird,尽管有 'succinct' 文档):
我在一个文件中有大约 9000 个左右的 URL,还有一些空行。我愿意:
- 过滤掉空行(url.length <= 0)
- 过滤掉那些不再响应的(通过使用
request
模块的 HEAD 请求) - MAP 通过
dns.resolve()
获取 IPv4 地址
- MAP 使用该 IPv4 地址和 http://ipinfo.io/xx.xx.xx.xx/geo 获取地理数据(好的,是的,每天有 API 限制,但假设我可以)
- 将结果信息作为JSONobjects的数组写入新文件
- 当然,这将 运行 并行进行,因此比顺序进行要快得多
第一个过滤器很简单,因为它会立即返回(这里使用 Bluebird):
Promise.each(urls, function(value, index, length) {
return value.length > 0;
}).then(
console.log(urls);
);
但是如何将异步head请求的结果反馈给Promise呢?这是我撞墙的另一个更完整的示例(请参阅内联评论):
<pre class="prettyprint lang-js">
var Promise = require('bluebird'),
request = Promise.promisifyAll(require('request'));
var urls = ["", "https://google.com/", "http://www.nonexistent.url"];
var checkLength = function(url) {
return Promise.resolve(url.length > 0);
}
var checkHead = function(url) {
return Promise.resolve(
// ??? seee below for an 'unPromised' function that works on its own
)
}
var logit = function(value) {
console.log((urls.length - value.length) + " empty line(s)");
}
Promise
.filter(urls, checkLength)
// and here? .filter(urls, checkHead) ? I don't think this would work.
// and I haven't even look at the map functions yet, although I guess
// that once I've understood the basic filter, map should be similar.
.then(logit);
</pre>
对于 checkHead
函数,我计划修改如下:
var isURLvalid = function(url) {
request
.head(url)
.on('response', function(response) {
console.log("GOT SUCCESS: " + response);
callback(response.statusCode < 300);
})
.on('error', function(error) {
console.log("GOT ERROR: " + response);
callback(false);
})
};
虽然不想抱怨,但我仍在拼命寻找一些好的入门教程 material,它可以让不熟悉 Promises 的开发人员亲身体验并展示常见用例的实际实现,cookbook-like.如果有的话,我很乐意得到一些指点。
过滤器和映射函数的工作方式与 JavaScript 数组的默认函数相同。
我之前使用过带有承诺的请求,并且有一个专门用于此的特定模块,称为 request-promise。可能更方便。
我确实觉得 request-promise 模块很棒,可以展示 Promise 的伟大之处。
与其陷入回调地狱,每个添加的请求都会更深入,你可以用 promises 来代替
rp(login)
.then(function(body) {
return rp(profile);
})
.then(function(body) {
return rp(profile_settings);
})
.then(function(body) {
return rp(logout);
})
.catch(function(err) {
// the procedure failed
console.error(err);
});
我将你当前的代码重写为这个
var Promise = require("bluebird");
var rp = require("request-promise");
var urls = ["", "https://google.com/", "http://www.nonexistent.url"];
Promise
// checkLength
.filter(urls, function(url){return url.length > 0})
.then(function(list) {
// logit
console.log((urls.length - list.length) + " empty line(s)");
// checkHead
return Promise.filter(list, function(url) {
// using request-promise and getting full response
return rp.head({ uri: url, resolveWithFullResponse: true })
.promise().then(function(response) {
// only statusCode 200 is ok
return response.statusCode === 200;
})
.catch(function(){
// all other statuscodes incl. the
// errorcodes are considered invalid
return false;
});
})
})
.then(console.log);