【问题标题】:Completing one array of mongoose requests before beginning another with Promise.all在使用 Promise.all 开始另一个请求之前完成一组 mongoose 请求
【发布时间】:2017-12-18 04:44:35
【问题描述】:

我正在使用 forEach 循环创建两个承诺数组。我需要在第二个请求开始之前完全完成第一个请求。然而,当我检查我的日志时,我发现“第一条”和“第二条”消息没有以正确的顺序出现,即使我认为我配置了承诺,以便它们会出现。帮我弄清楚我做错了什么?

谢谢。

function saveInstance(){
    return new Promise((resolve,reject)=>{
        var saveInstances = [];
        dateStarts.forEach(dateStart=>{
            var trimmedDate = siteBody.substr(dateStart+dateNeedle.length, 400).trim();
            var trimmedDateArray = trimmedDate.split(',');
            var instanceId = trimmedDateArray[0].substr(7,6);
            titleRecords.findOne({"titleByDate.instanceId": instanceId}, function(err,data){
                if (err) throw err;
                if (!data & trimmedDateTime !=null){
                    var instancerecord = new titleRecords();
                    instancerecord.titleByDate.instanceId      = instanceId;
                    instancerecord.newTitle                    = 1;
                    saveInstances.push(instancerecord.save(function(err,data){
                    console.log('This should print first');
                    err ? reject(): resolve();
                }));
                }               
            })
        })  
    Promise.all(saveInstances).then(updateInstanceTime,reject); 
    })
}

function updateInstanceTime(){
    return new Promise((resolve,reject)=>{
        var updateInstanceTimes = [];
        dateStarts.forEach(dateStart=>{
            var trimmedDate = siteBody.substr(dateStart+dateNeedle.length, 400).trim();
            var trimmedDateArray = trimmedDate.split(',');
            var titleTitle = trimmedDateArray[1].substr(2, trimmedDateArray[1].trim().length-2);
            var instanceId = trimmedDateArray[0].substr(7,6);

            var conditions      = {'titleByDate.instanceId'  : instanceId};
            var update          = {'titleByDate.lastSeen': localISOTime };
            updateInstanceTimes.push(titleRecords.update(conditions, update,function(err,data){
                console.log('This should print second');
                (err) ? reject() : resolve();
            }));
        })
    Promise.all(updateInstanceTimes).then(resolve,reject);  
    })
}

saveInstance();

【问题讨论】:

    标签: javascript node.js mongodb mongoose promise


    【解决方案1】:

    您的代码很难推理,因为您混合了节点回调和承诺。如果您使用承诺,请坚持下去。

    1. 通常您不需要手动创建 Promise。众所周知的“被遗忘的承诺”anti-pattern
    2. 使用 Promisified 版本的方法不要将回调与 Promises 混合使用。
    3. !data & trimmedDateTime !=null & - 是按位和运算符。我相信你想要&&
    4. 不要使用forEach 来创建另一个包含转换项的数组。有map

    这是一个如何重写第一个函数的示例。你应该对第二个做同样的事情。

    function saveInstance() {
      return Promise.all(
        dateStarts.map(dateStart => {
          var trimmedDate = siteBody.substr(dateStart + dateNeedle.length, 400).trim();
          var trimmedDateArray = trimmedDate.split(',');
          var instanceId = trimmedDateArray[0].substr(7, 6);
    
          return titleRecords.findOne({
              "titleByDate.instanceId": instanceId
            })
            .exec()
            .then(data => {
              if (!data) {
                var instancerecord = new titleRecords();
                instancerecord.titleByDate.instanceId = instanceId;
                instancerecord.newTitle = 1;
    
                return instancerecord.save()
              }
              return data
            })
        })
      ).then(updateInstanceTime)
    }
    

    【讨论】:

    • 感谢您的回复。那是一篇关于“被遗忘的承诺”的有趣文章——我不知道。你能帮我弄清楚如何承诺 console.log 回调,以便我可以测试它是否以正确的顺序运行?
    • @garson 简单的方法是定义一个点击函数const tap = result => (console.log(result), result) 然后使用任何你喜欢的承诺。例如return instancerecord.save().then(tap)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-06
    • 1970-01-01
    • 1970-01-01
    • 2020-03-04
    • 2020-09-24
    • 2013-10-15
    • 1970-01-01
    相关资源
    最近更新 更多