[英]in chained promises, if first promise require to not to execute rest of the promises, how
我有 4 個方法,每個方法都返回一個 Promise,並且它們是鏈式結構。 但不是我在第一個 Promise 中有一個可以滿足的條件,所以在這種情況下,我需要/不應該在鏈中執行剩余的 Promise。 我怎樣才能做到這一點?
這是正在完成的 4 個任務
任務1)查看Mongo中是否存在數據,如果不存在
任務 2) 調用 SOAP 服務
任務 3) 使用來自 SOAP 的結果,操作數據
任務 4) 將此文檔放入 Mongo
這工作正常,但是當任務 1 有數據時,我不應該處理接下來的 3 個承諾(任務 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
});
}
我如何實現這一目標? 謝謝。
我怎樣才能做到這一點?
使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); }); }
我喜歡 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
});
});
一般來說,有多種方法可以解決這個問題。
其中之一是:
catch()
getDataFromMongo
方法(帶有我們可以稍后實際檢查的“虛擬”錯誤)這不是最好的,但它不會破壞或顯着改變你現有的承諾鏈(如果你願意改變你的承諾鏈,你很可能應該遵循 TJ 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});
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.