我是Promises
的新手,我一直在阅读Q Documentation,其中说的是:
当你到达承诺链的末尾时,你应该返回最后的承诺或结束链。
我已经在我的代码中以Q.Promise
方式定义了一个Promise,并使用以下console.log
来注销执行跟踪:
function foo(){
return Q.Promise(function(resolve, reject) {
doSomething()
.then(function() {
console.log('1');
return doSomething1();
})
.then(function() {
console.log('2');
return doSomething2();
})
.then(function() {
console.log('3');
return doSomething3();
})
.catch(function(err) {
console.log('catch!!');
reject(err);
})
.done(function() {
console.log('done!!');
resolve();
});
});
}
如果每个doSomethingN()
正确执行,一切都按预期工作,我得到预期的跟踪:
1
2
3
done!!
但,以防任何doSomethingN()
失败:
foo()
正常工作,因为错误函数回调是在reject(err)
发生时运行的回调:
foo().then(function() { /* */ }, function(err) { /* this runs! */ });
我得到以下跟踪(即doSomething1()
失败时):
1
catch!!
done!!
我最初的想法如下:
好的,让我们在
.done()
和.catch()
方法中处理链接成功和失败。如果一切顺利,.done()
将执行回调并且承诺将解决。如果在任何时候出现错误,将执行.catch()
的回调并且承诺将被拒绝 - 正因为如此,{{1}不会被执行。
我想我错过了关于done()
如何工作的事情......因为通过查看我的日志记录,我意识到.done()
似乎总是在执行 - 是否有错误并且.done()
已执行或未执行 - 而这正是我所期待的。
因此,在此之后,我删除了.catch()
的回调,现在.done()
:
foo()
我应该重新考虑什么?我应该如何/应该让它发挥作用?
答案 0 :(得分:5)
catch(cb)
只是then(null, cb)
的别名,您实际上已修复错误catch
,因此流程自然转向成功结果为done
。
如果你只想装饰 catch中的错误,你应该在之后重新抛出错误,例如:适当的passthru可能看起来像:
catch(function (err) {
console.log(err);
throw err;
});
你的例子仍然没有多大意义。当你返回一个承诺时,你永远不应该使用done
。如果要使用内部创建的promise链解决初始化的promise,则应将其解析为:
resolve(doSomething()
.then(function() {
console.log('1');
return doSomething1();
})
....
.then(function() {
console.log('N');
return doSomethingN();
}));
不需要内部错误处理,将其留给您返回的承诺消费者。
还有其他一点。如果在创建新承诺时,您知道它将与其他承诺一起解决,那么创建此类承诺没有合理的理由,只需重用您计划解决的承诺。这种错误也被创造为deferred anti-pattern
答案 1 :(得分:2)
你应该考虑这样做:
fstream& Go2Line(fstream& file, unsigned int num){
file.seekg(ios::beg);
for(unsigned int i=0; i < num - 1; ++i)
file.ignore(numeric_limits<streamsize>::max(),'\n');
return file;}
int main(){
fstream file("testo.csv",ios_base::in);
if (!file)
cout << "Unable to open file file.csv\n";
else
{
int Number2Go = 1;
Go2Line(file, Number2Go);
if (!file)
cout << "Unable to reach line " << Number2Go << ".\n";
else
{
string line;
getline(file,line);
std::stringstream convertor(line);// I Don't know how continue from here
}
}
return 0;}
如果你想返回一个承诺,在大多数情况下使用catch没有多大意义(除非你想恢复潜在的错误)。在返回promise的方法中使用function foo() {
// Calling .then() on a promise still return a promise.
// You don't need Q.Promise here
return doSomething()
.then(function(doSomethingResult) {
console.log('1');
return doSomething1();
})
.then(function(doSomething1Result) {
console.log('2');
return doSomething2();
})
.then(function(doSomething2Result) {
console.log('3');
return doSomething3();
});
}
foo()
.then(function(fooResult) {
console.log(fooResult); // fooResult should be what is returned by doSomething3()
})
.catch(function(err) {
console.error(err); // Can be thrown by any
})
.done(function() {
console.log('I am always executed! error or success');
});
永远不会有意义。你宁愿在链的最后使用这些方法。
请注意,done
可以返回值或承诺,它将起作用。
答案 2 :(得分:0)
您可以通过在上一次然后回调中解析承诺来使其发挥作用。
function foo(){
return doSomething()
.then(function() {
console.log('1');
return doSomething1();
})
.then(function() {
console.log('2');
return doSomething2();
})
.then(function() {
console.log('3');
return doSomething3();
})
}
考虑将bluebird用于承诺。与任何其他promise库相比,它具有许多有用的功能。你可能会发现它很难开始,但是一旦掌握了它,你就会喜欢它。