2016-09-27 150 views
2

我有4个方法,每个返回一个承诺,我有他们的链结构。但是我不能在第一个Promise中有条件满足,所以在这种情况下,我需要/不应该在链中执行剩余的Promise。我怎样才能做到这一点?在链接的承诺,如果第一个承诺要求不执行其余的承诺,如何

这里是正在完成

任务1中的4个任务)使用,看看是否在蒙戈存在的数据,如果不

任务2)调用SOAP服务

任务3)从SOAP结果,操纵数据

任务4)把这个文档中蒙戈

这工作得很好,但是当任务1有数据,那么I S不能处理接下来的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 
    }); 
} 

如何实现这一目标?谢谢。

+0

如果有数据,调用'拒绝()'。 – 2016-09-27 11:57:50

+0

在这种情况下,如果您的条件得到满足(您会收到您需要的数据),请执行您的任务,并解决或拒绝未解决的链接承诺。 – Redu

+0

你可以提供更多关于你想要做什么的信息吗?我在想你的设计可能存在一些缺陷。 – bflemi3

回答

0

一般情况下,有多种方法来解决这个问题。

其中之一是:

  • 使用您的“四大任务链”
  • “拒绝”(但不是作为一个“错误”)的情况下, 的getDataFromMongo方法的现有后附加catch()数据(使用一个“虚拟”的错误,我们可以实际检查 后来)
  • “鸭打字”链本身
的拒绝原因210

这是不是最好的,但它不会打破,也没有显著改变现有承诺的链(如果你愿意改变你的链条,你应该最有可能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}); 
    }); 
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

我爱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 
    }); 
});