我的 Cloud 功能停止使用 Flutter Web 有啥重大变化吗?
Posted
技术标签:
【中文标题】我的 Cloud 功能停止使用 Flutter Web 有啥重大变化吗?【英文标题】:Did anything major change that my Cloud functions stopped working with flutter web?我的 Cloud 功能停止使用 Flutter Web 有什么重大变化吗? 【发布时间】:2021-08-16 14:04:34 【问题描述】:我曾经运行 Firebase Cloud Functions。但是在将我的整个代码库重构为听起来空安全之后,云功能停止工作(遗憾的是,我无法在时间轴的哪个点重现)..
pubspec.yaml
dependencies:
flutter:
sdk: flutter
firebase_core: ^1.0.2
firebase_auth: ^1.0.1
cloud_firestore: ^1.0.4
cloud_functions: ^1.1.0
...
网页/index.html
...
<script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/8.6.1/firebase-functions.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.19.1/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.19.1/firebase-firestore.js"></script>
<script>
// Your web app's Firebase configuration
var firebaseConfig =
apiKey: "<myApiKey>",
authDomain: "<my-project>.firebaseapp.com",
databaseURL: "https://<my-project>.firebaseio.com",
projectId: "<my-project>",
storageBucket: "<my-project>.appspot.com",
messagingSenderId: "<myMessageSenderId>",
appId: "<myAppId>"
;
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
firebase.functions().useFunctionsEmulator("http://10.0.2.2:5001");
</script>
<script src="main.dart.js" type="application/javascript"></script>
</body>
</html>
函数/index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const UserPropertyValue = require('firebase-functions/lib/providers/analytics');
admin.initializeApp();
exports.setRoles = functions.https.onCall((data, context) =>
let userId = null;
let userCustomClaimsAdmin = false;
let userCustomClaimsEditor = false;
// get user and update custom claim
return admin.auth().getUserByEmail(data.email).then(user =>
userId = user.uid;
const currentCustomClaims = (user.customClaims == undefined) ? : user.customClaims;
switch (data.role)
case 'admin':
currentCustomClaims.admin = (data.permission == 'grant') ? true : false;
break;
case 'editor':
currentCustomClaims.editor = (data.permission == 'grant') ? true : false;
break;
default:
return;
userCustomClaimsAdmin = currentCustomClaims.admin;
userCustomClaimsEditor = currentCustomClaims.editor;
return admin.auth().setCustomUserClaims(userId,
currentCustomClaims
);
).then(() =>
// Update User record in Firestore
return admin.firestore().collection("users").doc(userId).update(
isAdmin: userCustomClaimsAdmin,
isEditor: userCustomClaimsEditor,
);
).then(() =>
return
message: 'Success'
)
.catch(err =>
console.log(err.toString());
);
);
最后我调用函数:
...
final HttpsCallable setRoleCallable = FirebaseFunctions.instance
.httpsCallable('setRoles',
options:
HttpsCallableOptions(timeout: const Duration(seconds: 10)));
...
try
final HttpsCallableResult result = await setRoleCallable.call(
<String, dynamic>
'email': "<emailOfUserToBeChanged>",
'role': "<selectedRole>",
'permission': "<givenAccess>"
,
);
print(result.data);
on FirebaseFunctionsException catch (e)
print('caught firebase functions exception');
print(e.code);
print(e.message);
print(e.details);
catch (e)
print('caught generic exception');
print(e);
那个调用(在 localhost 和 10.0.2.2 上的模拟函数)结束于
caught firebase functions exception
internal
internal
null
在此期间我错过了什么变化吗?我在 Firebase 文档中找不到有关此主题的任何内容。
也许在某个我还没有意识到的时候发生了一些小变化..
【问题讨论】:
【参考方案1】:嗯,Cloud Functions 的一个重大变化是您现在必须拥有付费 Firebase 计划才能使用云功能,因为他们遗憾地从免费层中删除了 Cloud Functions .
【讨论】:
谢谢,这个提示可能对未来的读者有用。在我的情况下,我为该项目使用 Blaze-Plan :)【参考方案2】:在您的 Cloud Function 中,您无需等待异步操作完成后再发回响应。有关此关键方面的更多详细信息,请参阅doc。
棘手的是它会产生一些“不稳定”的行为(有时有效,有时无效),可以解释如下:
在某些情况下,您的云函数会在异步操作完成之前终止,如上述文档中所述。
但是,在某些其他情况下,Cloud Functions 平台可能不会立即终止您的 CF,从而为完成异步操作提供足够的时间。
所以你的印象是“云功能停止与 Flutter Web 一起工作”,而实际上,有时它可以工作,而其他一些时候则不行......
此外,请注意setCustomUserClaims()
方法返回Promise<void>
而不是user
,因此您需要为userId 和声明保留一组全局变量,以便从一个then()
传递它阻止对方。
所以以下应该可以解决问题(未经测试):
exports.setRoles = functions.https.onCall((data, context) =>
console.log('user to change email: ' + data.email);
let userId = null;
let userCustomClaimsAdmin = false;
let userCustomClaimsEditor = false;
// get user and update custom claim
return admin.auth().getUserByEmail(data.email)
.then(user =>
userId = user.uid; // the setCustomUserClaims() method returns a Promise<void> not a user !!
const currentCustomClaims = (user.customClaims == undefined) ? : user.customClaims;
switch (data.role)
case 'admin':
currentCustomClaims.admin = (data.permission == 'grant') ? true : false;
break;
case 'editor':
currentCustomClaims.editor = (data.permission == 'grant') ? true : false;
break;
default:
return;
break;
// Here you need to adapt the value of userCustomClaimsAdmin and userCustomClaimsEditor
userCustomClaimsAdmin = ...
userCustomClaimsEditor = ...
// See return below !!!!
return admin.auth().setCustomUserClaims(user.uid,
currentCustomClaims
);
)
.then(() =>
// See return below !!!!
return admin.firestore().collection("users").doc(userId).update(
isAdmin: (userCustomClaimsAdmin) ? user.customClaims.admin : false,
isEditor: (userCustomClaimsEditor) ? user.customClaims.editor : false,
);
)
.then(() =>
return
message: 'Success'
)
.catch(err =>
console.log(err.toString());
// !!!! See the doc: https://firebase.google.com/docs/functions/callable#handle_errors
);
);
【讨论】:
非常感谢。我将相应地更改代码并稍后发布结果... 好吧,我更改了 index.js(也更新了这篇文章),但错误/结果保持不变。 你需要适配部分//Here you need to adapt the value...
我想,我做到了?!我用 currentCustomClaims 的值设置全局变量。否则我在这里很无助。你的意思是?也许我只是没有做对..
你应该用一些logging来调试代码。【参考方案3】:
好吧,我正在开发一个 Flutter-Web 项目。我使用的是 cloud-functions,而不是 cloud-functions-web。
在我的 main.dart 中缺少使用函数模拟器的指令:
...
Future<void> main() async
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseFunctions.instance
.useFunctionsEmulator(origin: 'http://localhost:5001'); // this was missing
runApp(MyApp());
...
它曾经可以工作,因为我的 index.html 中已经有该指令
...
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
firebase.functions().useFunctionsEmulator("http://10.0.2.2:5001");
...
尽管如此,它现在可以工作了。
【讨论】:
以上是关于我的 Cloud 功能停止使用 Flutter Web 有啥重大变化吗?的主要内容,如果未能解决你的问题,请参考以下文章
Cloud Firestore 连接我的 Flutter Windows 应用
添加 cloud_firebase 包后,我的 Flutter App 没有运行
Flutter/cloud-firestore“任务已经完成”异常