Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/40.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 同步环路_Javascript_Node.js_Mongoose_Promise - Fatal编程技术网

Javascript 同步环路

Javascript 同步环路,javascript,node.js,mongoose,promise,Javascript,Node.js,Mongoose,Promise,我想在我的代码中做一个同步循环。 函数saveInDatabase检查数据库中是否已经存在项标题(字符串)。这就是为什么不能并行地解决它,否则该条件将永远不会应用(并将创建重复项) 我尝试将此函数封装为单独的承诺,也尝试了npm包(synchronous.js,sync),但它似乎不适合我的代码 也许这个解决方案完全是愚蠢的。 您认为用同步循环(例如foreach)取代promise.all是一个更好的主意吗?问题是我需要每次迭代的结果 我正在使用节点6.11.2。你能给我一些处理这个问题的建议

我想在我的代码中做一个同步循环。 函数saveInDatabase检查数据库中是否已经存在项标题(字符串)。这就是为什么不能并行地解决它,否则该条件将永远不会应用(并将创建重复项)

我尝试将此函数封装为单独的承诺,也尝试了npm包(synchronous.js,sync),但它似乎不适合我的代码

也许这个解决方案完全是愚蠢的。 您认为用同步循环(例如foreach)取代promise.all是一个更好的主意吗?问题是我需要每次迭代的结果

我正在使用节点6.11.2。你能给我一些处理这个问题的建议吗?
先谢谢你

如果不使用
await
(node.js v6.11.2中没有,但会使这更简单),序列化一组返回承诺的异步操作的经典模式是使用
reduce()
循环,如下所示:

arr.reduce(function(p, item) {
    return p.then(function() {
        return saveInDatabase(item).then((myResult) => ... );
    });
}, Promise.resolve()).then(function() {
    // all done here
}).catch(function(err) {
    // error here
});
Promise.all(arr.map(item => {
     return saveInDatabase(item).then((myResult) => ... );
})).then(function(results) {
    // all done here
}).catch(function(err) {
    // error here
});
如果要保存所有结果,可以使用
。然后(myResult=>…)
处理程序
。将结果推入一个数组,完成后可以访问该数组

这将序列化对
saveInDatabase(item)
的所有调用,它在调用第二个之前等待第一个调用完成,在调用第三个之前等待第二个调用完成,等等

如果
saveInDatabase(item)
拒绝,此处的默认实现将停止。如果您想继续(您的问题中没有说明),即使它给出了一个错误,您也可以向它添加一个
.catch()
,将被拒绝的承诺变成已履行的承诺


在node.js v7+中,您可以在常规的
for
循环中使用
wait

async function myFunc() {
    let results = [];
    for (let item of arr) {
        let r = await saveInDatabase(item).then((myResult) => ... );
        results.push(r);
    }
    return results;
}

myFunc().then(function(results) {
    // all done here
}).catch(function(err) {
    // error here
});

如果您可以并行运行所有请求,那么您可以这样做:

arr.reduce(function(p, item) {
    return p.then(function() {
        return saveInDatabase(item).then((myResult) => ... );
    });
}, Promise.resolve()).then(function() {
    // all done here
}).catch(function(err) {
    // error here
});
Promise.all(arr.map(item => {
     return saveInDatabase(item).then((myResult) => ... );
})).then(function(results) {
    // all done here
}).catch(function(err) {
    // error here
});

在其中任何一种情况下,如果您不希望它在被拒绝时停止,那么在您的
saveInDatabase()
承诺链中添加一个
.catch()
,将拒绝转化为一个已解决的承诺,其中包含一些您可以检测到的已知值或错误值。

promise.all可能是用于此作业的错误工具。您需要一次运行一个,与传递给promise.all的数组相比,用.then链表示更好<代码>[].reduce
如果您有一个数组
让looper=(当前,最大值)=>{saveInDatabase(arr[current]),则可以为您设置该链;活套(0,棱长)只是给你一个想法,你知道。。。无论如何,在我看来,这一切在概念上都是错误的(在本例中),请参阅。
同步循环
对于异步代码来说,永远都不是解决方案。如果希望在最后一次迭代完成后访问所有结果,那么使用Promise.all并不一定是错误的。您正在使用
.map
而没有从
.map
回调返回任何内容,这意味着您已经在使用
.map
,就好像它是
.forEach
一样!谢谢你的解释。不过有件事困扰着我。如果我将所有结果放入一个数组,这将无法解决在数据库中检查是否存在任何重复项(根据其标题)的问题。我想我将修改saveInDatabase函数的用途:它只返回所有项的列表,而不是在数据库中随意“保存”。然后我可以检查最终数组中的重复条件。是的,我忘了告诉你一个项目可以返回子项目,等等。。。