[英]Promise chains and anonymous promise returns
在这里,我有一连串的诺言,效果很好。 所有* .destroy都是返回诺言的诺言:
function callDBDestroy() {
var db;
DB_Categories.destroy().then(function () {
return DB_Equipment.destroy();
}).catch(function (err) {
showMsg("Error in callDBDestroy: " + err);
}).then(function () {
return DB_Certificates.destroy();
}).catch(function (err) {
showMsg("Error in callDBDestroy: " + err);
}).then(function () {
return DB_Locations.destroy();
}).catch(function (err) {
showMsg("Error in callDBDestroy: " + err);
});
}
但我想在每个语句中添加一个if语句,以检查PouchDB数据库是否存在(如果DB_ *为null,则不存在)。
如果存在,我想销毁它,然后返回(所有这些返回诺言)。
如果不存在,我想返回一个匿名承诺,该承诺不返回任何内容,因为这些承诺都没有我关心的任何数据。
在该示例中,我添加了一些示例代码来执行if语句,并且我想知道我将在将传递一个promise(解析)值的null实例中放入什么。
function callDBDestroy() {
var db;
DB_Categories.destroy().then(function () {
if( DB_Equipment != null) {
return DB_Equipment.destroy();
}
else {
Anonymous empty promise - something like:
new Promise().resolve();
}
}).then(function () {
return DB_Certificates.destroy();
}).then(function () {
return DB_Locations.destroy();
}).catch(function (err) {
showMsg("Error in callDBDestroy: " + err);
});
}
谢谢,
汤姆
看来您只是想知道如何手动解决/拒绝Promise。 如果是这种情况,如果您想转到catch
处理程序,则可以仅调用Promise.resolve(optionalValue)
或Promise.reject(optionalValue)
:
function callDBDestroy() {
var db;
DB_Categories.destroy()
.then(function () {
if( DB_Equipment != null) {
return DB_Equipment.destroy();
} else {
return Promise.resolve();
}
}).then(function () {
return DB_Certificates.destroy();
}).then(function () {
return DB_Locations.destroy();
}).catch(function (err) {
showMsg("Error in callDBDestroy: " + err);
});
}
您可以将其包装:
function withDb(db, handler) {
return function onFulfilled(value) {
if(db === null) throw new Error("DB Null");
return handler(value);
});
}
哪个可以让您做:
function callDBDestroy() {
var db;
var w = withDb(db); // or whatever instance
DB_Categories.destroy().then(w(function () {
// do stuff
}))); // .then(w( to chain calls here.
...
}
我想返回一个匿名诺言,该诺言不返回任何内容,因为这些诺言都没有我关心的任何数据。 就像是:
new Promise().resolve();
您正在寻找Promise.resolve(undefined)
。 尽管您可以省略undefined
,但这是隐式的。
….then(function () {
if (DB_Equipment != null) {
return DB_Equipment.destroy();
} else {
return Promise.resolve(undefined);
}
}).…
而且,您甚至不必从then
回调中返回promise,只需返回undefined
(或不return
ing)将具有相同的效果。
….then(function () {
if (DB_Equipment != null) {
return DB_Equipment.destroy();
}
}).…
在您的情况下,我建议使用包装函数:
function destroyDatabase(db, name = "db") {
if (db != null)
return db.destroy().catch(err => {
showMsg(`Error in destroying ${name}: ${err}`);
});
else
return Promise.resolve();
}
function callDBDestroy() {
return destroyDatabase(DB_Categories, "categories")
.then(() => destroyDatabase(DB_Certificates, "certificates"))
.then(() => destroyDatabase(DB_Locations, "locations"))
}
// or even in parallel:
function callDBDestroy() {
return Promise.all([
destroyDatabase(DB_Categories, "categories"),
destroyDatabase(DB_Certificates, "certificates"),
destroyDatabase(DB_Locations, "locations")
]);
}
由于您执行相同的任务,并且只有数据库发生更改,因此如何使用数组:
//serial
function callDBDestroy() {
var databases = [
DB_Categories,
DB_Equipment,
DB_Certificates,
DB_Locations
];
function errorMessage(err){ showMsg("Error in callDBDestroy: " + err) };
databases.reduce(
(prev, db) => db == null?
prev:
prev.then(() => db.destroy().catch(errorMessage)),
Promise.resolve()
)
}
//parallel
function callDBDestroy() {
var databases = [
DB_Categories,
DB_Equipment,
DB_Certificates,
DB_Locations
];
function errorMessage(err){ showMsg("Error in callDBDestroy: " + err) };
databases.forEach( db => db && db.destroy().catch(errorMessage) );
}
我添加了一个序列号和一个paralell版本。
似乎您可以使用数据库数组对此进行干燥 ,并替换许多冗余代码,然后循环遍历该数组:
function callDbDestroy();
var dbs = [DB_Categories, DB_Equipment, DB_Certificates, DB_Locations];
// chain all the destroys together
return dbs.reduce((p, db) => {
return p.then(() => {
if (db) {
return db.destroy().catch(err => {
showMsg("Error in callDBDestroy: " + err);
});
}
});
}, Promise.resolve());
}
您不必从.then()
处理函数返回承诺。 如果您没有返回值,则就像执行return undefined
,这意味着没有值将传递给下一个.then()
处理程序,但是promise链将继续正常运行。 从概念上讲,它的工作原理与return Promise.resolve()
相同,但是不需要在那里做额外的承诺。
由于您没有将值从一个.then()
传递到链中的下一个,因此您没有任何要传递的值,因此,如果没有db
值可以调用destroy,则无法返回任何内容。
仅供参考,使用.reduce()
遍历数组与return p.then(...)
结构是用于对数组上的异步操作进行排序的常见设计模式。
仅供参考,使用Bluebird Promise库(具有一些有用的帮助程序),可以这样进行:
function callDbDestroy();
var dbs = [DB_Categories, DB_Equipment, DB_Certificates, DB_Locations];
return Promise.mapSeries(dbs, db => {
if (db) {
return db.destroy().catch(err => {
showMsg("Error in callDBDestroy: " + err);
});
}
});
}
有关为何即使在ES6上Bluebird(或其他Promise库)仍然有用的更多信息,请参阅既然有了ES6 Promise , 是否还有理由使用Q或BlueBird这样的Promise库?
由于这些数据库似乎都可能是独立的,所以我想知道为什么要强制它们按顺序执行。 如果不必强制将它们顺序排列,则可以执行以下操作:
function callDbDestroy();
var dbs = [DB_Categories, DB_Equipment, DB_Certificates, DB_Locations];
return Promise.all(dbs.map(db => {
if (db) {
return db.destroy().catch(err => {
showMsg("Error in callDBDestroy: " + err);
});
}
}));
}
由于这可以并行运行操作,因此有机会缩短端到端的执行时间,而不是严格的序列化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.