我有一个系统想要使用api在保管箱中创建许多文件夹,但是我似乎试图立即创建所有文件夹,这会导致产生错误,说明我从保管箱执行了太多写操作。
我的代码如下,首先使用reduce来创建多个我认为已链接的promise。在这些承诺中,调用了add函数,该函数将案例上传到mongodb,然后为其创建一个保管箱文件夹,但这会导致节流错误。
bulkAdd: function (req, callback) {
issues = []
i = 1
req.reduce((promise, audit) => {
return promise.then(_ => this.add(audit, function(err,data){
if (err){
console.log('\n'+i+ ' ' + data.scanner_ui + '\n');
}
}));
}, Promise.resolve()).catch(error => {console.log(error)});
},
add: function (req, callback) {
delete req.status
var audit = new Audit(req);
if (req['status_value'] != undefined && req.status_value != ''){
console.log(req['status_value'])
audit.status = [{
status_value : req['status_value'],
status_notes : req['status_notes'],
status_date : req['status_date'],
}]
}
audit.save(function (err, data) {
if (err) {
callback(err, data)
}
else {
return dropbox_functions.createFolder(data.ui)
.then(response => {console.log(response)}, error=> {console.log('\n\n\n',error.error.error)})
.catch(error => console.log(error))
}
});
},
答案 0 :(得分:2)
因此,您当前问题中的问题出在您的add
函数没有返回值的事实上,我只看到它返回未定义的值。
如果一个承诺在其then
/ catch
块中返回了一个承诺以外的东西,它将使用此输入执行以下功能,并且它将不等待任何内部进程运行之前完成
如果在您的then
/ catch
块中,您将返回一个承诺,它将等待继续下一个then
块,从而顺序处理请求。
现在,在您当前的代码中,我认为最简单的方法是处理reduce内的解析,因为您似乎已经被回调句柄卡住了。
req.reduce((promise, audit) => {
return promise.then(_ => new Promise(
function( resolve, reject) {
this.add(audit, function(err,data){
if (err){
console.log('\n'+i+ ' ' + data.scanner_ui + '\n');
reject( err );
return;
}
resolve( data );
});
})
);
}, Promise.resolve()).catch(error => {console.log(error)});
在这种情况下,承诺本身可能是reject
或resolve
。我选择分别提交err
和data
,以便最终在发生错误的情况下进行处理,以便您可以成功保存最后保存的数据
答案 1 :(得分:0)
要正确链接,应确保返回一个Promise对象。
您的reduce最终会创建类似这样的承诺链。
Promise.resolve()
.then(() => {
console.log('setting up first timeout');
setTimeout(() => {
console.log("1 wait");
}, 2000);
})
.then(() => {
console.log('setting up second timeout');
setTimeout(() => {
console.log("2 wait");
}, 2000);
})
.catch(err => console.log("error", err));
如果您运行它,您会发现它在向下移动链之前不会等待一个承诺结束。
在第二个示例中,它等待第一个示例完成,因为第一个Promise返回了Promise对象。
Promise.resolve()
.then(() => {
return new Promise(function(resolve, reject) {
console.log('setting up first timeout');
setTimeout(() => {
console.log("1 wait");
resolve();
}, 2000);
});
})
.then(() => {
return new Promise(function(resolve, reject) {
console.log('setting up second timeout');
setTimeout(() => {
console.log("2 wait");
resolve();
}, 2000);
});
})
.catch(err => console.log("error", err));
区别在于第一个示例不返回Promise对象。因此,如果您确保每个成功处理程序都返回一个Promise对象,而该对象仅在您的add函数执行完后才能解决,那么您就可以了。
答案 2 :(得分:0)
除非有充分的理由将bulkAdd()
编写为nodeback风格,否则您将发现返回承诺更加方便。对nodeback的需求将消失,.reduce()
将更舒适地位于函数内部。
使用.reduce()
并保留nodeback样式是可能的,但很麻烦,因为它涉及从nodeback到promise以及从诺言回到nodeback的相当丑陋的双重改组。
假设您可以随意调整呼叫者以接受返回的promise,则代码将如下所示:
'bulkAdd': function(req) {
return req.reduce((promise, audit) => {
return promise.then(_ => this.add(audit));
}, Promise.resolve());
},
'add': function(req) {
delete req.status;
var audit = new Audit(req);
if (req.status_value != undefined && req.status_value != '') {
audit.status = [{
'status_value': req.status_value,
'status_notes': req.status_notes,
'status_date': req.status_date
}];
}
return new Promise((resolve, reject) => { // in-line promisification of audit.save()
audit.save((err, data) => {
err ? reject(err) : resolve(data);
});
})
.then(data => dropbox_functions.createFolder(data.ui));
},
所有捕获和日志记录均已故意删除
细节可能有所不同,主要取决于: