return statement在变量的foreach之外返回null值,我知道foreach循环会创建自己的范围,我需要返回该值,我该怎么做.....
this.selectedUserMessages = this.changeUserList.switchMap(Userid => {
if (Userid) {
var self = this;
this.loadingSerivice.isLoading.next(true);
var ref = db.database.ref(`wfffsdf/usesdfdsfsrs/${Userid}/ress`);
var i = 0;
ref.once("value")
.then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var key = childSnapshot.key;
// childData will be the actual contents of the child
var invitedList = childSnapshot.val();
self.invList.push({
invitedid: invitedList
});
var invitedlistid = self.invList[i]['invitedid']['invitedBy'];
//console.log(invitedlistid);
if (invitedlistid == "asfsafafasfsafsafs") {
//console.log("thread"+threadKey);
self.ChatKey = key;
//console.log(self.ChatKey+""+ db.database.ref(`1dfgsdfgdfhfdh/tdfsdfhsfhfhfdh/${key}/messages`));
}
i++;
});
self.chatMessages = self.getMessages(self.ChatKey);
// console.log(self.chatMessages);
});
return this.chatMessages;
}
return of(null);
}
返回this.chatMessages为空值...
答案 0 :(得分:1)
最简单的答案是变量的范围不是问题。在Javascript中,var
的作用域是周围的函数。在提供的示例代码中,forEach
被传递给function
,因此其所有变量的作用域均与声明的作用域相同。外部变量被捕获在内部函数中,因此它们也可以正常运行。
问题在于内部promise
在switchmap
返回值之前没有解析。
要完全了解正在发生的事情,让我们看一下代码当前正在执行的操作以及应该执行的操作。
为了争辩,我将假设以下定义(即使我知道它们是不正确的):
selectedUserMessages : Observable<[]>;
changeUserList : Observable<String>;
此处,changeUserList
是代表当前所选UserId
的字符串事件流。 selectedUserMessages
将是与当前所选用户相关联的消息数组。
上面的代码简化为以下含义:
this.selectedUserMessages =
// when changeUserList changes, switch selectedUserMessages to this new stream
this.changeUserList.switchMap(Userid => {
if (Userid) {
// grab DB reference to user child list
var ref = db.database.ref(`wfffsdf/usesdfdsfsrs/${Userid}/ress`);
// CREATE A PROMISE TO QUERY THE DATABASE
ref.once("value") // query once
.then(function (snapshot) {
snapshot.forEach(function (childSnapshot) {
var key = childSnapshot.key;
var val = childSnapshot.val();
// process child
});
// store result
this.chatMessages = this.getMessages(this.ChatKey);
}); // END OF PROMISE
// RETURN IMMEDIATELY, BEFORE PROMISE RESOLVES
return this.chatMessages;
}
return of(null); // return null stream
}
问题是switchmap调用在内部承诺解决之前返回this.chatMessages
。
switchmap
具有一个有趣的功能:您可以可以从switchmap内部返回一个承诺,它将等待该承诺。这是mix Promises and Observables的一种方式。
从switchmap内部返回一个承诺,就像:
this.selectedUserMessages =
// when changeUserList changes, switch selectedUserMessages to this new stream
this.changeUserList.switchMap(Userid => {
if (Userid) {
// grab DB reference to user child list
let ref = db.database.ref(`wfffsdf/usesdfdsfsrs/${Userid}/ress`);
// !!!! RETURN A PROMISE TO QUERY THE DATABASE !!!!
return ref.once("value") // query once
.then(function (snapshot) {
let results = [];
snapshot.forEach(function (childSnapshot) {
let key = childSnapshot.key;
let val = childSnapshot.val();
// process child //
results.push(/*processing results*/);
});
return results;
}); // END OF PROMISE
}
else
return of(null); // return null stream
}
话虽这么说,但还有一种替代方案,可以混合用于Firebase的Promises和Observables RxFire。这是Firebase团队使用RxJS Observables的相对较新的软件包。由于您正在使用实时数据库,因此您将需要look at these examples。 List()将发出子更改流。您可以通过pipe()
运算符map()
将此流进行其他处理(或如示例中那样提取val()并包含密钥)。您在map()中执行的操作类似于在forEach
中执行的操作。
AngularFirebase有一个在FireStore上使用RxFire的示例。