我有4个方法,每个方法都返回一个Promise,我将它们放在链式结构中。但是我没有在第一个Promise中有条件可以满足,所以在这种情况下我需要/不应该在链中执行剩余的Promise。我怎么能这样做?
这里有4项正在完成的任务
任务1)查看Mongo中是否存在数据,如果不存在
任务2)调用SOAP服务
任务3)使用SOAP的结果,操纵数据
任务4)将此文档放入Mongo
这很好,但是当任务1有数据时,我不应该处理下3个Promises(任务2,3,4)。
这是我目前的代码
checkMongoForData(req, res)
.then(function (result) {
return makeTheSOAPcall(req, res, result)
.then(function (result) {
return fillTheReasonDescriptions(req, res, result);
})
.then(function (result) {
return upsertTheRespDocInMongo(req, res, result);
})
.then(function (result) {
res.status(200);
res.send({result: 'success', status: 200});
})
.catch(function (reject) {
res.status(reject.status);
res.send({result: reject.description, status: reject.status});
});
//我的函数定义了类似这样的东西
function checkMongoForData(req, res) {
return new Promise(function (resolve, reject) {
// TODO : the logic goes here
/// check to see for the data. If not there then continue
// if there is data, no need to do remaining tasks
});
}
我如何实现这一目标?感谢。
答案 0 :(得分:1)
我该怎么做?
制作checkMongoForData
=> getDataFromMongo
并在没有数据时拒绝它。然后使用catch
来捕获拒绝并触发获取数据的调用链:
getDataFromMongo(req, res)
.catch(function() {
// Didn't get the data, go get it
return makeTheSOAPcall(req, res, result)
.then(function (result) {
return fillTheReasonDescriptions(req, res, result);
})
.then(function (result) {
return upsertTheRespDocInMongo(req, res, result);
});
})
.then(function (result) {
// Got the data (one way or another)
res.status(200);
res.send({result: 'success', status: 200});
})
.catch(function (reject) {
// Something went irretrievably wrong
res.status(reject.status);
res.send({result: reject.description, status: reject.status});
});
如果upsertTheRespDocInMongo
的分辨率值不是数据本身,您可能需要在其上添加.then
来更改输出内容。
以下是一个例子:
var fakeMongo = Object.create(null);
function getDataFromMongo(key) {
console.log("getDataFromMongo: ", key);
return new Promise(function(resolve, reject) {
setTimeout(function() {
if (Object.prototype.hasOwnProperty.call(fakeMongo, key)) {
// We have the data
resolve({key: key, value: fakeMongo[key]});
} else {
// We don't have the data
reject();
}
}, 100);
});
}
function makeTheSOAPcall(key) {
console.log("makeTheSOAPcall: " + key);
return new Promise(function(resolve) {
resolve({
key: key,
value: "value for " + key
});
});
}
function fillTheReasonDescriptions(result) {
console.log("fillTheReasonDescriptions: " + result.key);
return Promise.resolve(result);
}
function upsertTheRespDocInMongo(result) {
console.log("upsertTheRespDocInMongo: " + result.key);
return new Promise(function(resolve) {
fakeMongo[result.key] = result.value;
resolve(result);
});
}
// Usage
retrieve("key1") // Get key1 (won't be there)
.then(function() {
return retrieve("key2"); // Get key2 (won't be there)
})
.then(function() { // Get key1 again (will be there)
return retrieve("key1");
})
function retrieve(key) {
console.log("retrieve: " + key);
return getDataFromMongo(key/*req, res*/)
.catch(function() {
// Didn't get the data, go get it
return makeTheSOAPcall(key/*req, res*/)
.then(function(result) {
return fillTheReasonDescriptions(/*req, res, */result);
})
.then(function(result) {
return upsertTheRespDocInMongo(/*req, res, */result);
});
})
.then(function(result) {
// Got the data (one way or another)
console.log("Got the data:", result);
})
.catch(function(reject) {
// Something went irretrievably wrong
console.log("Somethingw went wrong", reject);
});
}
答案 1 :(得分:1)
我喜欢ES6,因为我认为代码更具可读性。
var reply = msg => {
res.status(msg.status);
res.send(msg);
};
var fetchAndUpdate = result =>
makeTheSOAPcall(req, res, result)
.then(result => fillTheReasonDescriptions(req, res, result))
.then(result => upsertTheRespDocInMongo(req, res, result));
checkMongoForData(req, res)
.then(result =>
//This is the key change. If result is not enpty, then return a promise
//resolve, else call fetchAndUpdate which returns a promise, which will.
//be resolved (or rejected) eventually.
result ? Promise.resolve() : fetchAndUpdate(result))
.then(() => reply({result: 'success', status: 200}))
.catch(e => reply({result: e.description, status: e.status}));
ES5
var reply = function(msg) {
res.status(msg.status);
res.send(msg);
};
var fetchAndUpdate = function(result) {
return makeTheSOAPcall(req, res, result).then(function(result) {
return fillTheReasonDescriptions(req, res, result);
}).then(function(result) {
return upsertTheRespDocInMongo(req, res, result);
});
};
checkMongoForData(req, res).then(function(result) {
return result ? Promise.resolve() : fetchAndUpdate(result);
}).then(function() {
return reply({
result: "success",
status: 200
});
}).catch(function(e) {
return reply({
result: e.description,
status: e.status
});
});
答案 2 :(得分:0)
一般来说,有多种方法可以解决这个问题。
其中一个是:
catch()
getDataFromMongo
方法
现有数据(带有"虚拟"我们实际可以检查的错误
后)它不是最好的,但它不会破坏也不会显着改变你现有的承诺链(如果你愿意改变你的链条,你很可能会选择this answer by T.J. Crowder ):
// This can be anything, as long as it's "unique"
var dummyError = "has no data";
function checkMongoForData(req, res) {
return new Promise(function (resolve, reject) {
// TODO: Replace with your logic
var hasData = false;
var data = "";
if (hasData) {
resolve(data);
} else {
reject(dummyError);
}
});
}
checkMongoForData(req, res)
.then(function (result) {
return makeTheSOAPcall(req, res, result)
})
.then(function (result) {
return fillTheReasonDescriptions(req, res, result);
})
.then(function (result) {
return upsertTheRespDocInMongo(req, res, result);
})
.catch(function (error) {
if (error === dummyError) {
return;
}
// This line "re-throws"/"re-rejects" the error object
return Promise.reject(error);
})
.then(function (result) {
res.status(200);
res.send({result: 'success', status: 200});
})
.catch(function (reject) {
res.status(reject.status);
res.send({result: reject.description, status: reject.status});
});