我需要实现
系统我使用类似的回调工作解决方案。
MongoClient.connect(dsn).then(function(db) {
parentcollection.findOne({"_id" : new ObjectId(pid)}, function(err, data) {
var redis = require("redis"),
client = redis.createClient();
client.on("error", function (err) {
console.log("Error " + err);
});
// If not set
client.get(cacheKey, function(err, data) {
// data is null if the key doesn't exist
if(err || data === null) {
var options = {
host: HOST,
port: 80,
path: URI
};
var req = http.get(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
body += chunk;
//console.log('CHUNK: ' + chunk);
});
res.on('end', function () {
data = JSON.parse(body);
// Get childdata After process of data
childcollection.save(childdata, {w:1}, function(cerr, inserted) {
db.close();
});
});
});
} else {
// Get childdata from cache data
childcollection.save(childdata, {w:1}, function(cerr, inserted) {
db.close();
});
}
});
});
我想使用promise(原生的,而不是像bluebird / request这样的外部代码)而不是回调。我查看手册并思考是否需要像那样实现
var promise1 = new Promise((resolve, reject) => {
MongoClient.connect(dsn).then(function(db) {
parentcollection.findOne({"_id" : new ObjectId(pid)}, function(err, data) {
});
}}.then(function(data){
var promise2 = new Promise((resolve, reject) => {
var redis = require("redis"),
client = redis.createClient();
client.on("error", function (err) {
console.log("Error " + err);
});
// If not set
client.get(cacheKey, function(err, data) {
// data is null if the key doesn't exist
if(err || data === null) {
var options = {
host: HOST,
port: 80,
path: URI
};
var promise3 = new Promise((resolve, reject) => {
var req = http.get(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
body += chunk;
//console.log('CHUNK: ' + chunk);
});
res.on('end', function () {
data = JSON.parse(body);
// Get childdata After process of data
});
})
}).then(function(data){
childcollection.save(childdata, {w:1}, function(cerr, inserted) {
db.close();
});
});
} else {
// Get childdata from cache data
childcollection.save(childdata, {w:1}, function(cerr, inserted) {
db.close();
});
}
});
}}.then(function(data){
});
});
看起来像回调地狱一样脏,或者没有使用上述承诺的任何更好的方法?
答案 0 :(得分:1)
一个问题是,您永远不会调用提供给promise构造函数回调的 resolve 函数。没有打电话给他们,承诺永远不会解决。
我建议在单独的,可重用的函数中创建这些新的promise。另一方面,当您不提供回调参数时,一些MongoDb方法已经返回promise。
你可以这样做。
// Two promisifying functions:
function promiseClientData(client, key) {
return new Promise(function (resolve, reject) {
return client.get(key, function (err, data) {
return err ? reject(err) : resolve(data); // fulfull the promise
});
});
}
function promiseHttpData(options) {
return new Promise(function (resolve, reject) {
return http.get(options, function(res) {
var body = ''; // You need to initialise this...
res.setEncoding('utf8');
res.on('data', function (chunk) {
body += chunk;
//console.log('CHUNK: ' + chunk);
});
res.on('end', function () {
data = JSON.parse(body);
resolve(data); // fulfull the promise
});
);
});
}
// Declare the db variable outside of the promise chain to avoid
// having to pass it through
var db;
// The actual promise chain:
MongoClient.connect(dsn).then(function (dbArg) {
db = dbArg;
return parentcollection.findOne({"_id" : new ObjectId(pid)}); // returns a promise
}).then(function (data) {
var redis = require("redis"),
client = redis.createClient();
client.on("error", function (err) {
console.log("Error " + err);
});
// Get somehow cacheKey...
// ...
return promiseClientData(client, cacheKey);
}).then(function (data) {
// If not set: data is null if the key doesn't exist
// Throwing an error will trigger the next `catch` callback
if(data === null) throw "key does not exist";
return data;
}).catch(function (err) {
var options = {
host: HOST,
port: 80,
path: URI
};
return promiseHttpData(options);
}).then(function (data) {
// Get childdata by processing data (in either case)
// ....
// ....
return childcollection.save(childdata, {w:1}); // returns a promise
}).then(function () {
db.close();
});
我认为MongoDb返回的承诺是完全合规的。有疑问,您可以通过调用Promise.resolve()
将它们转换为本机JavaScript承诺,例如:
return Promise.resolve(parentcollection.findOne({"_id" : new ObjectId(pid)}));
或:
return Promise.resolve(childcollection.save(childdata, {w:1}));