簡體   English   中英

在鏈式承諾中,如果第一個承諾要求不執行其余的承諾,如何

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM