var verifyEmail = function (thisEmail){
return new Promise(
function (resolve, reject) {
quickemailverification.verify(thisEmail, function (err, response) {
// Print response object
console.log(response.body);
if (response.body["success"] == "true"){
var validity = response.body["result"];
if (validity == "valid"){
console.log("Email Valid!");
resolve(validity);
} else {
console.log("Email Invalid!")
resolve(validity);
}
} else {
var reason = new Error("API unsuccessful");
reject(reason);
}
});
}
);
};
var saveValidity = function (validity){
return new Promise(
function (resolve, reject){
if (validity == "valid"){
var state = true;
admin.database().ref("/users_unverified/"+keys[i]+"/emails/"+x+"/verified/").set(state, function(error) {
if (error) {
console.log("Email ("+thisEmail+") verfication could not be saved" + error);
}
console.log("Email verification saved: " +thisEmail);
});
} else {
state = false;
admin.database().ref("/users_unverified/"+keys[i]+"/emails/"+x+"/verified/").set(state, function(error) {
if (error) {
console.log("Email ("+thisEmail+") verfication could not be saved" + error);
}
console.log("Email verification saved: " +thisEmail);
});
}
}
);
};
admin.database().ref("/users_unverified/").once('value').then(function(snapshot) {
var snap = snapshot.val();
keys = Object.keys(snap);
for (var i = 0; i < 100; i++){
var emails = snap[keys[i]]["emails"];
if (emails){
for (var x = 0; x<emails.length; x++){
var thisEmail = emails[x]["email"];
var emailVerified = emails[x]["verified"];
if (emailVerified != true || emailVerified != false){
verifyEmail
.then(saveValidity)
.then(function (fulfilled) {
console.log(fulfilled);
})
.catch(function (error){
console.log(error.message);
});
}
}
}
}
});
以上是我放在一起的代码。我不太相信它会起作用。我是承诺的新手,所以我试图理解如何做到这一点。
verifyEmail函数应该从代码的第三个块中的firebase查询中获取电子邮件地址。 saveValidity函数应该接受来自verifyEmail的有效性响应。
但是,我还担心我在firebase查询块中嵌套的for循环。我正在遍历每个用户以验证他们的电子邮件,但每个用户有时也会有多封电子邮件。我担心它会在完成检查前一个用户的所有电子邮件之前循环到下一个用户。
我也不确定我是否可以按照我的方式将数据传递到promise函数。
绝对可以在这里使用一些帮助。真的很难理解它是如何工作的。
答案 0 :(得分:1)
首先,您需要修复saveValidity()
以始终解析或拒绝承诺,并传入其引用的其他变量key
和thisEmail
:
const saveValidity = function (validity, key, thisEmail){
return new Promise(
function (resolve, reject){
if (validity == "valid"){
let state = true;
admin.database().ref("/users_unverified/"+key+"/emails/"+x+"/verified/").set(state, function(error) {
if (error) {
let msg = "Email ("+thisEmail+") verfication could not be saved" + error;
console.log(msg);
reject(new Error("Email ("+thisEmail+") verfication could not be saved" + error));
} else {
resolve("Email verification saved: " +thisEmail);
}
});
} else {
state = false;
admin.database().ref("/users_unverified/"+keys[i]+"/emails/"+x+"/verified/").set(state, function(error) {
if (error) {
let msg = "Email ("+thisEmail+") verfication could not be saved" + error;
console.log(msg);
reject(new Error(msg));
} else {
resolve("Email verification saved: " +thisEmail);
}
});
}
}
);
};
然后,对您的主循环进行了一些更改:
verifyEmail()
个调用,因为它们似乎没有任何关系。verifyEmail.then(...)
更改为verifyEmail(thisEmail).then(...)`实际调用该函数verifyEmail()
承诺Promise.all()
以监控它们何时完成.then()
返回值,以便我们在Promise.all()
.catch()
,因此保证会被拒绝,并会过滤回Promise.all()
。如果你想忽略它们并继续其他人,你可能会在这里吃错误。var
切换到let
!=
更改为!==
,因为看起来您明确要查找true
或false
值,并且不希望进行类型转换。saveValidity()
需要的变量。emailVerified
时更改逻辑,因为之前的内容始终是正确的,因此可能不是正确的逻辑。我想你想要知道什么时候emailVerified
尚未设置为true
或false
,这意味着您必须使用&&
,而不是||
。 for
圈与keys.length
进行比较,而不是100
的硬编码值。而且,这是主嵌套for
循环的结果代码:
admin.database().ref("/users_unverified/").once('value').then(function(snapshot) {
let snap = snapshot.val();
let keys = Object.keys(snap);
let promises = [];
for (let i = 0; i < keys.length; i++){
let key = keys[i];
let emails = snap[key]["emails"];
if (emails){
for (let x = 0; x < emails.length; x++) {
let currentKey = key;
let thisEmail = emails[x]["email"];
let emailVerified = emails[x]["verified"];
if (emailVerified !== true && emailVerified !== false){
promises.push(verifyEmail(thisEmail).then(validity => {
return saveValidity(validity, currentKey, thisEmail);
}).then(function (fulfilled) {
console.log(fulfilled);
return fulfilled; // after logging return value so it stays the resolved value
}).catch(function (error) {
console.log(error.message);
throw error; // rethrow so promise stays rejected
}));
}
}
}
}
return Promise.all(promises);
}).then(results => {
// all results done here
}).catch(err => {
// error here
});
答案 1 :(得分:1)
如果ES2017适用于您的情况,您只需使用关键字await
和async
即可直接执行此操作。以下是一个例子:
function resolveAfter2Seconds(x) {
return new Promise(resolve => {
setTimeout(() => {
resolve(x);
}, 2000);
});
}
async function f1() {
var x = await resolveAfter2Seconds(10);
console.log(x); // 10
}
f1();
您可以阅读有关async / await here的更多信息。
如果您希望在没有async / await的情况下执行此操作以获得更好的浏览器兼容性,则可以使用Babel进行预编译。
如果您真的想要一个lightwight实现,可以使用名为chainPromiseThunks
的函数,或简称chain
。这个chain
函数接受一组Promises Thunk,并返回一个新的Thunk of Promise,以下是chain
的一行实现:
const chain = thunks => thunks.reduce((r, a) => () => r().then(a));
这是一个用法演示:
const echo = x =>
new Promise(function(resolve) {
return setTimeout((function() {
console.log(x);
return resolve(x);
}), 1000);
})
;
const pThunks = [1,2,3,4,5].map(i => () => echo(i));
chain(pThunks)();