8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

useQueries 失去了并行查询数据的能力,因为 Next.js 要求服务器组件异步

Abdul Qadeer 3月前

114 0

该应用程序由 Next.js 运行。我有一个 useQueries 钩子:const userQueries = useQueries({ queries: user.contacts.map((contactId: string) => ({ queryKey: ['contact', conta...

该应用程序由 Next.js 运行。

我有一个 useQueries 钩子:

    const userQueries = useQueries({
        queries: user.contacts.map((contactId: string) => ({
            queryKey: ['contact', contactId],
            queryFn: () => getUserById(contactId),
        }))
    });

api.ts 文件中的函数“getUserById”:

export async function getUserById(userId: string) {
    const supabase = createClient();
    let {data} = await supabase
        .from('users')
        .select()
        .eq('id', userId);

    return data && data[0]

}

我发现当我以这种方式加载数据时,它会按顺序加载而不是并行加载。

我尝试将 api 函数设为非异步,以便每个请求不会等待前一个请求,但 Next.js 禁止在没有“async”前缀的情况下执行服务器操作。有办法解决这个问题吗?

帖子版权声明 1、本帖标题:useQueries 失去了并行查询数据的能力,因为 Next.js 要求服务器组件异步
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Abdul Qadeer在本站《typescript》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 我尝试将各种模块组合成一个连贯的 AZ DevOps 发布流程。其中一些模块仅支持 PowerShell 5.1 以上版本,但是,我尝试的功能

    我尝试将各种模块组合在一起,形成一个连贯的 AZ DevOps 发布流程。其中一些模块仅支持 PowerShell 5.1 及以上版本,但我尝试利用的功能在 PowerShell 7 中 - 特别是 ForeEach-Object -Parallel cmdlet。

    在函数中使用 Add-Type 'Microsoft.PowerShell.Core' 来调用 ForeEach-Object -Parallel 是否可行?脚本块调用一个可以作为 PoSh 5 或 7 运行的独立脚本。我知道我可以内联某些模块的下载和使用(即 ThreadJobs 显示在 6 中)。文档说我不能使用 Import-Module。

    我最希望使用的 ForEach-Object 功能是:-Parallel(显而易见)-ThrottleLimit 和 -AsJob。

    或者...停留在 7 并且对于不支持 7 的模块“降级”到 5 是否有意义?

    我将其用作 200 多个数据库的多租户数据库发布流程的一部分。有些数据库很大,需要一段时间,有些则不需要。我应用了大约 70 个脚本,包括备份、应用 MDM 数据、发布、回滚(失败)和状态报告。

    我们将非常感激您的见解和指导。

    我尝试从 PoSh 6 下载并导入 ThreadJob 模块,但收效甚微。我希望利用 7 和 FEO -Parallel 可以解决我的问题。

  • 我有一个 Nextjs 应用程序,它同时使用 React-Email、Resend 和 Firebase Cloud Functions。目录结构如下所示:每当在 & 中创建文档时,我都想向用户发送电子邮件...

    我有一个 Nextjs 应用,它同时使用了 React-Email、Resend 和 Firebase Cloud Functions。目录结构如下所示:

    enter image description here

    我希望每当在 \'emailVerification\' 集合中创建文档时向用户发送一封电子邮件,以下是云函数的样子:

    import * as logger from "firebase-functions/logger";
    import {onDocumentCreated} from "firebase-functions/v2/firestore";
    import { Resend } from 'resend'
    import EmailVerificationTemplate from '../../react-email/emails/EmailVerification'
    import { render } from '@react-email/components';
    
    const resend = new Resend(RESEND_API_KEY);
    
    export const sendEmailVerification = onDocumentCreated("/emailVerifications/{id}", async (event) => {
        // Grab the current value of what was written to Firestore.
        const data = event?.data?.data();
    
        // Access the parameter `{documentId}` with `event.params`
        logger.log("Requesting email verification for uid", event.params.id, data);
    
        const emailHtml = render(EmailVerificationTemplate({
            validationCode: data?.code.toString()
        }));
    
        await resend.emails.send({
            from: '[email protected]',
            to: data?.email,
            subject: 'Your Halbert Verification Code',
            html: emailHtml
        });
    
    });
    

    但是,当我尝试使用以下方法部署此功能时出现此错误:firebase deploy --only functions:

    enter image description here

    我该如何解决这些错误?

  • 我正在学习使用 ESP32 的 MQTT 服务器和客户端以及 UDP 协议。当代码中有两个线程时,ESP32 每秒都会重新启动,我遇到这个问题:一个用于发送,一个用于接收......

    我正在学习使用 ESP32 的 MQTT 服务器和客户端以及 UDP 协议。

    当代码中有两个线程时,ESP32 每秒都会重新启动,这是一个问题:一个用于发送 UDP 数据报,一个用于接收 UDP 数据报。有人能帮我解决这个问题吗?

    这是我的代码

    #include <WiFi.h>
        #include "AsyncUDP.h"
        #include <MQTT.h>
        #include <WiFiUdp.h>
        #include <OSCMessage.h>
    
        TaskHandle_t thread;
        
        WiFiClient net;
        const char* ssid = "---"; //some info
        const char* password = "---"; //some info
        
        IPAddress outIp(***, ***, ***, ***); //some info
        const unsigned int outPort = ----; //some info
        
        MQTTClient mqttClient;
        int port = ----; //some info
        long lastMillis = 0;
        String ping = "";
        String address = "";
        bool start = true;
        
        AsyncUDP udp;
        AsyncUDP udpThread;
        AsyncUDPMessage udpMsg;
        
        uint32_t timeConnect;
        uint32_t timeOffset;
        
        void setup() {
          Serial.begin(115200);
        
          xTaskCreatePinnedToCore(
            threadLoop, 
            "Thread",   
            10000,      
            NULL,      
            1,          
            &thread,    
            0);         
        
        
          ConnectToWifi(ssid, password, true);
          Serial.println("Connected to the Wi-Fi network");
        
          ping = GetPing();
          Serial.println(ping);
        }
        
        void loop() {
          OSCMessage msg("/ping");
          msg.add("Some message");
          msg.send(udpMsg);
          msg.empty();
          udp.sendTo(udpMsg, outIp, outPort);
          delay(1000);
        }
        
        void threadLoop(void* pvParameters) {
        
          if (udpThread.listen(port)) {
            String data[2];
            udpThread.onPacket([](AsyncUDPPacket packet) {
              //parse packet
            }
        
            if (data[0] == "***") {
              address = packet.remoteIP().toString(); 
              int addressLen = address.length() + 1;
        
              char broker[addressLen];
              address.toCharArray(broker, addressLen);
        
              mqttClient.begin(broker, net);
              mqttClient.onMessage(Received); //event subscription
        
              char* timeEnd;
              timeConnect = strtol(data[1].c_str(), &timeEnd, 0);
              timeOffset = millis() / 1000ul;
        
              start = true;
            }
          });
        
          while (1) {
            if (start) {
              mqttClient.loop();
              delay(10);
              if (!mqttClient.connected()) {
                ConnectedMQTT();
              }
              if (millis() - lastMillis > 1000) {
                lastMillis = millis();
        
                uint32_t sec = millis() / 1000ul;
                uint32_t time = timeConnect + (sec - timeOffset);
                mqttClient.publish(ping, String(time), true, 0);
              }
            } 
            else {
              udpThread.broadcastTo("***", port);
              delay(1000);
            }
          }
        }
    

    如果我替换这部分代码:

          if (udpThread.listen(port)) {
            String data[2];
            udpThread.onPacket(\[\](AsyncUDPPacket packet) {
              //parse packet
          }
        
          if (data[0] == "***") {
            address = packet.remoteIP().toString(); 
            int addressLen = address.length() + 1;
        
            char broker[addressLen];
            address.toCharArray(broker, addressLen);
        
            mqttClient.begin(broker, net);
            mqttClient.onMessage(Received); //event subscription
        
            char* timeEnd;
            timeConnect = strtol(data[1].c_str(), &timeEnd, 0);
            timeOffset = millis() / 1000ul;
        
            start = true;
          }
        });
    

    有了这个:

        char broker[] = "***, ***, ***, ***"; //some info
        mqttClient.begin(broker, net);
        mqttClient.onMessage(Received); //event subscription
    

    然后 ESP32 停止重启。

    此外,当我仅保留循环方法时,ESP32将停止重启:

        void loop() {       
          OSCMessage msg("/ping");       
          msg.add("Some message");       
          msg.send(udpMsg);      
          msg.empty();      
          udp.sendTo(udpMsg, outIp, outPort);   
          delay(1000);
        }
    
  • 我正在优化具有 64 个以上内核的 Windows 系统上的多线程应用程序。通常,我会使用 SetProcessAffinityMask 函数来设置 CPU 内核亲和性...

    我正在优化具有 64 个以上内核的 Windows 系统上的多线程应用程序。通常,我会使用 SetProcessAffinityMask 函数来设置整个进程的 CPU 内核亲和性,但由于 64 位掩码限制,这种方法仅限于具有最多 64 个内核的系统。

    虽然我知道 SetThreadGroupAffinity 函数,但它需要手动设置每个线程的亲和性,包括新线程的初始设置。我正在寻找一种设置亲和性的方法,该方法可以应用于进程外部,影响所有当前和未来的线程,而无需更改进程的内部代码来管理此亲和性。

    问题: 是否有任何方法或工具允许从外部为 Windows 进程设置和管理 CPU 核心亲和性,特别适合具有 64 个以上核心的系统?这些方法如何确保亲和性设置适用于进程内的所有线程?

  • 我在前端团队工作,服务器团队已开始使用不同的方法来处理 API 请求。他们现在要求我发送一个属性,其中包含我希望在

    我在前端团队工作,服务器团队已开始使用不同的方法来处理 API 请求。他们现在要求我发送一个属性,其中包含我希望在响应中返回的特定字段。

    例如:

    http.post(`/api/v1/users`, { requiredFields: [1, 2, 3] }) 
    // The response will be [{ firstname, lastname, age }]
    // This means that firstname is 1, lastname is 2, and so on.
    

    我想根据我发送的数字确保响应类型安全。

    这是一个模拟我需要发送的内容和我收到的内容的小函数:

    function server(fields) {
      const allFields = {
        1: 'firstname',
        2: 'lastname',
        3: 'age',
        4: 'address',
        5: 'email'
      };
    
      const result = {};
    
      fields.forEach(field => {
        if (allFields[field]) {
          result[allFields[field]] = null;
        }
      });
    
      return result;
    }
    

    我想过创建一个接口、类型、枚举或某种模式,但我不确定如何将其集成到 JavaScript 中。

  • 我正在开发一款专用于 Windows 的 MAUI C# 应用程序。这款应用程序的独特之处在于它与本地数据库配合使用,并调用填充服务器上数据库的 API。在此应用程序中,我有一个 p...

    我正在开发一款专用于 Windows 的 MAUI C# 应用程序。这款应用程序的独特之处在于它与本地数据库配合使用,并调用一个 API 来填充服务器上的数据库。在此应用程序中,我有一个显示项目列表的页面。在此页面上,我还有一些按钮,允许我添加/更新/删除此列表中的项目。这些按钮会调出一个用于更新或添加项目的模式。

    当我单击其中一个按钮时,模态框出现,然后我进行更改。由于模态框的背景是透明的,我可以看到修改已应用于列表。但是,模态框不会像代码中预期的那样自动关闭。我必须单击“退出”才能使模态框消失。

    返回列表后,如果我想再次与列表交互,我会单击其中一个按钮。模式打开,我执行操作(添加/更新),我看到修改正在进行,但模式没有关闭并冻结。如果我单击“退出”,我会收到此错误:Application.Current.MainPage.Navigation.ModalStack.Count = 0,并且应用程序崩溃。

    如果我将按钮中的所有逻辑都注释掉,我也会遇到同样的问题。

    我尝试了很多方法,但我觉得我在主线程管理中明显缺少了一些东西。我不太了解 MAUI 中的线程。有人能帮我吗?

    提前致谢。

    这是我的代码,其中我的列表的视图

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="FntrAudit.Views.RequiredDisplayPage"
                 Title="Affichage Obligatoire">
        <Grid RowDefinitions="Auto,*,Auto"
           ColumnDefinitions="*,*,*">
            <Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" Text="Affichages obligatoires" FontSize="Large"></Label>
    
            <ListView Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" ItemsSource="{Binding RequiredDisplays}">
                <ListView.ItemTemplate>
                    <DataTemplate >
                        <ViewCell>
                            <StackLayout Orientation="Horizontal" VerticalOptions="Center" Spacing="10">
                                <CheckBox IsChecked="{Binding IsOk}"  VerticalOptions="Center"/>
                                <Label Text="{Binding Intitule}" VerticalOptions="Center" HorizontalOptions="FillAndExpand" LineBreakMode="WordWrap"/>
                                <ImageButton Clicked="UpdateDoc" HeightRequest="20" WidthRequest="20" Source="update.png" CommandParameter="{Binding .}"></ImageButton>
                                <ImageButton Clicked="Delete_Clicked" HeightRequest="20" WidthRequest="20" Source="delete.png" CommandParameter="{Binding .}"></ImageButton>
                            </StackLayout>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
            <Button   BackgroundColor="#AE1439" Grid.Row="2" Grid.Column="1"  Text="Enregistrer et revenir à l'audit" Margin="5" Clicked="Record_Clicked" HorizontalOptions="Fill"></Button>
            <Button   BackgroundColor="#AE1439" Grid.Row="2" Grid.Column="0"  Text="Ajouter document obligatoire" Margin="5" Clicked="AddDoc" HorizontalOptions="Fill"></Button>
        </Grid>
    </ContentPage>
    

    背后的代码

    using FntrAudit.DALApi;
    using FntrAudit.Data;
    using FntrAudit.Models;
    using FntrAudit.Utils;
    using FntrAudit.Views.Modal;
    using Microsoft.EntityFrameworkCore;
    using System.Collections.ObjectModel;
    
    namespace FntrAudit.Views;
    
    public partial class RequiredDisplayPage : ContentPage
    {
        private Audit _audit;
        SqliteDbContext _db = new SqliteDbContext();
        private ObservableCollection<RequiredDisplay> requiredDisplays;
        private RestService<RequiredDisplay> _requiredDisplayService = new RestService<RequiredDisplay>();
        private RestService<LogFromApp> _LogService = new RestService<LogFromApp>();
        public ObservableCollection<RequiredDisplay> RequiredDisplays
        {
            get { return requiredDisplays; }
            set
            {
                if (requiredDisplays != value)
                {
                    requiredDisplays = value;
                    OnPropertyChanged(nameof(RequiredDisplays));
                }
            }
        }
        public RequiredDisplayPage(Audit audit)
        {
            InitializeComponent();
            _audit = audit;
            InitializeAsync();
        }
        private async void InitializeAsync()
        {
            await LoadRequiredDoc();
        }
    
        public async Task LoadRequiredDoc()
        {
            try
            {
                Console.WriteLine("Loading required documents...");
                bool hasWeb = Connectivity.Current.NetworkAccess == NetworkAccess.Internet;
                List<RequiredDisplay> requiredDisplays = new List<RequiredDisplay>();
    
    
                if (_audit.RequiredDisplay.Any(rd => rd.IsOk))
                {
                    RequiredDisplays = new ObservableCollection<RequiredDisplay>(_audit.RequiredDisplay);
                }
                else
                {
                    RequiredDisplays = new ObservableCollection<RequiredDisplay>(_audit.RequiredDisplay);
    
                }
    
                await Task.Delay(1000);
                this.BindingContext = this;
                Console.WriteLine("Required documents loaded successfully.");
            }
            catch(Exception ex)
            {
                var t = ex.Message;
                Console.WriteLine($"Error loading required documents: {ex.Message}");
            }
          
        }
    
        private async void Delete_Clicked(object sender, EventArgs e)
        {
            try
            {
                bool answer = await DisplayAlert("Supprimer un document obligatoire", "Êtes-vous sûr de vouloir supprimer ce document ?", "Oui", "Non");
    
                if (answer)
                {
                    if (sender is ImageButton button && button.CommandParameter is RequiredDisplay toDelete)
                    {
                        try
                        {
                            Console.WriteLine($"Attempting to delete document: {toDelete.GuidRDisplay}");
                            _db.RequiredDisplay.Remove(toDelete);
                            await _db.SaveChangesAsync();
                            await _requiredDisplayService.DeleteTodoItemAsync(toDelete.GuidRDisplay, Constantes.URLAPI + "RequiredDisplay/");
                            RequiredDisplays.Remove(toDelete);
                            Console.WriteLine($"Document {toDelete.GuidRDisplay} deleted successfully.");
                        }
                        catch (DbUpdateConcurrencyException)
                        {
                            await _db.Entry(toDelete).ReloadAsync();
                            await DisplayAlert("Échec de la suppression", "Le document a été modifié ou supprimé par une autre transaction. Veuillez réessayer.", "OK");
                            Console.WriteLine($"Concurrency error while deleting document: {toDelete.GuidRDisplay}");
                        }
                        catch (Exception ex)
                        {
                            LogFromApp logFromApp = new LogFromApp()
                            {
                                DateCreation = DateTime.Now,
                                Intitule = "ModalRequired delete doc (UserContext ContextCurrent) " + ex.Message,
                                Trace = ex.ToString(),
                                UserInvolved = " "
                            };
    
                            await _LogService.Create(logFromApp, Constantes.URLAPILOG, true);
                            await DisplayAlert("Erreur", "Une erreur est survenue lors de la suppression du document.", "OK");
                            Console.WriteLine($"Error deleting document: {ex.Message}");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                await DisplayAlert("Erreur", "Une erreur est survenue lors de la suppression du document.", "OK");
                Console.WriteLine("Erreur lors de la suppression du document : " + ex.Message);
            }
        }
    
        //public async void Delete_Clicked(object sender, EventArgs e)
        //{
        //    bool answer = false;
        //    try
        //    {
        //         answer = await DisplayAlert("Supprimer un document obligatoire", "Êtes-vous sûr de vouloir supprimer ce document ?", "Oui", "Non");
        //    }
        //    catch(Exception ex)
        //    {
        //        var toto = ex.Message;
        //    }
    
        //    if (answer)
        //    {
        //        if (sender is ImageButton button && button.CommandParameter is RequiredDisplay toDelete)
        //        {
        //            try
        //            {
        //                _db.RequiredDisplay.Remove(toDelete);
        //                _db.SaveChanges();
        //                await _requiredDisplayService.DeleteTodoItemAsync(toDelete.GuidRDisplay, Constantes.URLAPI + "RequiredDisplay/");
        //                RequiredDisplays.Remove(toDelete);
        //            }
        //            catch (DbUpdateConcurrencyException ex)
        //            {
        //                // Option 1: Raffraîchir l'entité depuis la base de données
        //                await _db.Entry(toDelete).ReloadAsync();
    
        //                // Afficher un message d'erreur à l'utilisateur
        //                await DisplayAlert("Échec de la suppression", "Le document a été modifié ou supprimé par une autre transaction. Veuillez réessayer.", "OK");
    
        //                // Option 2: Tentative de réexécution de la suppression après rechargement
        //                // _db.RequiredDisplay.Remove(toDelete);
        //                // _db.SaveChanges();
        //            }
        //            catch (Exception ex)
        //            {
        //                // Afficher un message d'erreur générique
        //                await DisplayAlert("Erreur", "Une erreur est survenue lors de la suppression du document.", "OK");
        //            }
        //        }
        //    }
        //}
        public async void Record_Clicked(object sender, EventArgs e)
        {
            try
            {
                Console.WriteLine("Recording clicked.");
                _audit.RequiredDisplay = RequiredDisplays.ToList();
                await Application.Current.MainPage.Navigation.PopModalAsync();
                Console.WriteLine("Modal closed successfully.");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error in Record_Clicked: {ex.Message}");
            }
        }
        public async void AddDoc(object sender, EventArgs e)
        {
            try
            {
                RequiredDisplay requiredDisplay = new RequiredDisplay();
                var modal = new ModalRequiredDisplay(requiredDisplay, true);
                modal.RequiredDisplays = this.RequiredDisplays;
                //  await Application.Current.MainPage.Navigation.PushModalAsync(modal);
    
                var tcs = new TaskCompletionSource<bool>();
                modal.Disappearing += async (s, args) =>
                {
                    Console.WriteLine("Modal disappearing...");
                    if (!tcs.Task.IsCompleted)
                    {
                        tcs.SetResult(true);
                    }
    
                };
                await Application.Current.MainPage.Navigation.PushModalAsync(modal);
                await tcs.Task;  // Wait for the modal to close
                await LoadRequiredDoc();
            }
            catch(Exception ex)
            {
                Console.WriteLine($"Error in AddDoc: {ex.Message}");
            }
           
           
        }
    
        public async void UpdateDoc(object sender, EventArgs e)
        {
            try
            {
                if (sender is ImageButton button && button.CommandParameter is RequiredDisplay toUpdate)
                {
                    var modal = new ModalRequiredDisplay(toUpdate, false);
                    modal.RequiredDisplays = this.RequiredDisplays;
    
                    var tcs = new TaskCompletionSource<bool>();
                    modal.Disappearing += (s, args) =>
                    {
                        Console.WriteLine("Modal disappearing...");
                        if (!tcs.Task.IsCompleted)
                        {
                            tcs.SetResult(true);
                        }
                    };
    
                    await Application.Current.MainPage.Navigation.PushModalAsync(modal);
                    Console.WriteLine("Modal pushed to stack.");
                    await tcs.Task;  // Wait for the modal to close
                    Console.WriteLine("Modal closed.");
                    await LoadRequiredDoc();
                }
            
            }catch(Exception ex)
            {
                var t = ex.Message;
            }
        }
    }
    

    情态动词

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="FntrAudit.Views.Modal.ModalRequiredDisplay"
                 BackgroundColor="#00000000"
                 Title="Affichage Obligatoire">
        <ContentView HorizontalOptions="Center" VerticalOptions="Center">
            <ScrollView>
                <Frame BackgroundColor="White" CornerRadius="20" Padding="20"
                   HorizontalOptions="Center" VerticalOptions="Center"
                   WidthRequest="700" HeightRequest="600">
               
                <VerticalStackLayout Spacing="15">
                    <Label Text="{Binding TitleModal}" TextColor="Black" FontSize="24" FontAttributes="Bold" HorizontalOptions="Center"></Label>
    
                    <Editor Text="{Binding Intitule}" Placeholder="Intitulé du document" AutoSize="TextChanges"></Editor>
    
                    <VerticalStackLayout Spacing="10">
                        <Label Text="Effectif de l'entreprise concernée (si besoin)" VerticalOptions="CenterAndExpand" FontAttributes="Bold"/>
                        <VerticalStackLayout Spacing="5">
                            <Grid ColumnDefinitions="Auto,*,Auto" RowDefinitions="Auto" Padding="5">
                                <Label Text="Toutes" Grid.Column="0" VerticalOptions="CenterAndExpand" Margin="0,0,10,0"/>
                                <RadioButton x:Name="All" GroupName="Effectif" IsChecked="True" Grid.Column="2" VerticalOptions="CenterAndExpand"/>
                            </Grid>
                            <Grid ColumnDefinitions="Auto,*,Auto" RowDefinitions="Auto" Padding="5">
                                <Label Text="de 1 à 10" Grid.Column="0" VerticalOptions="CenterAndExpand" Margin="0,0,10,0"/>
                                <RadioButton x:Name="Has1SalOrMore" GroupName="Effectif" IsChecked="{Binding Has1SalOrMore}" Grid.Column="2" VerticalOptions="CenterAndExpand"/>
                            </Grid>
                            <Grid ColumnDefinitions="Auto,*,Auto" RowDefinitions="Auto" Padding="5">
                                <Label Text="de 11 à 50" Grid.Column="0" VerticalOptions="CenterAndExpand" Margin="0,0,10,0"/>
                                <RadioButton x:Name="Has11SalOrMore" GroupName="Effectif" IsChecked="{Binding Has11SalOrMore}" Grid.Column="2" VerticalOptions="CenterAndExpand"/>
                            </Grid>
                            <Grid ColumnDefinitions="Auto,*,Auto" RowDefinitions="Auto" Padding="5">
                                <Label Text="de 51 à 300" Grid.Column="0" VerticalOptions="CenterAndExpand" Margin="0,0,10,0"/>
                                <RadioButton x:Name="Has50SalOrMore" GroupName="Effectif" IsChecked="{Binding Has50SalOrMore}" Grid.Column="2" VerticalOptions="CenterAndExpand"/>
                            </Grid>
                            <Grid ColumnDefinitions="Auto,*,Auto" RowDefinitions="Auto" Padding="5">
                                <Label Text="de 301 à 1000" Grid.Column="0" VerticalOptions="CenterAndExpand" Margin="0,0,10,0"/>
                                <RadioButton x:Name="Has300SalOrMore" GroupName="Effectif" IsChecked="{Binding Has300SalOrMore}" Grid.Column="2" VerticalOptions="CenterAndExpand"/>
                            </Grid>
                            <Grid ColumnDefinitions="Auto,*,Auto" RowDefinitions="Auto" Padding="5">
                                <Label Text="1000 et plus" Grid.Column="0" VerticalOptions="CenterAndExpand" Margin="0,0,10,0"/>
                                <RadioButton x:Name="Has1000SalOrMore" GroupName="Effectif" IsChecked="{Binding Has1000SalOrMore}" Grid.Column="2" VerticalOptions="CenterAndExpand"/>
                            </Grid>
                        </VerticalStackLayout>
                    </VerticalStackLayout>
    
                    <HorizontalStackLayout Spacing="10">
                        <Button BackgroundColor="#007AFF" TextColor="White" Text="Enregistrer" Margin="5" Clicked="AddDoc_Clicked" HorizontalOptions="FillAndExpand"></Button>
                        <Button BackgroundColor="#FF3B30" TextColor="White" Text="Quitter" Margin="5" Clicked="Quit_Clicked" HorizontalOptions="FillAndExpand"></Button>
                    </HorizontalStackLayout>
                </VerticalStackLayout>
            </Frame>
            </ScrollView>
        </ContentView>
    </ContentPage>
    

    背后的代码

    using CommunityToolkit.Maui.Alerts;
    using FntrAudit.DALApi;
    using FntrAudit.Data;
    using FntrAudit.Models;
    using FntrAudit.Services;
    using FntrAudit.Utils;
    using Microsoft.EntityFrameworkCore;
    using System.Collections.ObjectModel;
    
    namespace FntrAudit.Views.Modal;
    
    public partial class ModalRequiredDisplay : ContentPage
    {
        private RequiredDisplay _document;
        private bool _isCreation;
        SqliteDbContext _db = new SqliteDbContext();
        private ObservableCollection<RequiredDisplay> requiredDisplays;
        private RestService<RequiredDisplay> _requiredDisplayService = new RestService<RequiredDisplay>();
        private RestService<LogFromApp> _LogService = new RestService<LogFromApp>();
        
        public ObservableCollection<RequiredDisplay> RequiredDisplays
        {
            get { return requiredDisplays; }
            set
            {
                if (requiredDisplays != value)
                {
                    requiredDisplays = value;
                    OnPropertyChanged(nameof(RequiredDisplays));
    
                }
            }
        }
        public ModalRequiredDisplay(RequiredDisplay document, bool isCreation)
        {
            InitializeComponent();
            _document = document;
            _isCreation = isCreation;
            
            _document.TitleModal = _isCreation ? "Ajout d'un document obligatoire" : "Mise à jour d'un document obligatoire";
           
            this.BindingContext = _document;     
        }
    
        private async void Delete_Clicked(object sender, EventArgs e)
        {
            await CloseModalAsync();
        }
    
        private async void Quit_Clicked(object sender, EventArgs e)
        {
            await CloseModalAsync();
        }
    
       
    
        private async Task AddDoc(object sender, EventArgs e)
        {
            bool hasWeb = Connectivity.Current.NetworkAccess == NetworkAccess.Internet;
           
            try
            {
                if (_isCreation)
                {
    
                    RequiredDisplay required = new RequiredDisplay();
                    _document.IsOk = false;
                    _document.AuditId = 1;
                    _document.GuidRDisplay = Guid.NewGuid().ToString();
    
                    await _db.RequiredDisplay.AddAsync(_document);
                    await _db.SaveChangesAsync();
    
                    Func<Task> saveDocument = async () =>
                    {
                        await _requiredDisplayService.Create(_document, Constantes.URLAPI + "RequiredDisplay", true);
                    };
    
                    if (hasWeb)
                    {
                        await saveDocument.Invoke();
                    }
                    else
                    {
                        var connectivityService = new ConnectivityService();
                        connectivityService.AddTask(saveDocument);
                    }
                }
                else
                {
                    _db.Update(_document);
                    await _db.SaveChangesAsync();
    
                    Func<Task> updateDocument = async () =>
                    {
                        await _requiredDisplayService.Create(_document, Constantes.URLAPI + "RequiredDisplay/RequiredDisplay/" + _document.GuidRDisplay, false);
                    };
    
                    if (hasWeb)
                    {
                        await updateDocument.Invoke();
                    }
                    else
                    {
                        var connectivityService = new ConnectivityService();
                        connectivityService.AddTask(updateDocument);
                    }
    
                }
               
                await ShowToasterAsync("Document obligatoire enregistré avec succès.");
            }
            catch (Exception ex)
            {
                LogFromApp logFromApp = new LogFromApp()
                {
                    DateCreation = DateTime.Now,
                    Intitule = "ModalRequired (UserContext ContextCurrent) " + ex.Message,
                    Trace = ex.ToString(),
                    UserInvolved = " "
                };
    
                await _LogService.Create(logFromApp, Constantes.URLAPILOG, true);
            }
            finally
            {
                try
                {
                    if (RequiredDisplays == null)
                    {
                        RequiredDisplays = new ObservableCollection<RequiredDisplay>();
                    }
    
                    RequiredDisplay requiredDisplay = null;
    
                    if (RequiredDisplays.Count > 0 && _document != null)
                    {
                        requiredDisplay = RequiredDisplays.FirstOrDefault(rd => rd.GuidRDisplay == _document.GuidRDisplay);
                    }
    
                    if (requiredDisplay != null)
                    {
                        int index = RequiredDisplays.IndexOf(requiredDisplay);
                        if (index != -1)
                        {
                            RequiredDisplays[index] = _document;
                        }
                    }
    
                    await CloseModalAsync();
                }
                catch (Exception closeEx)
                {
                    Console.WriteLine("Erreur lors de la fermeture de la modal : " + closeEx.Message);
                }
    
            }
        }
    
        private async Task CloseModalAsync()
        {
            try
            {
                if (Application.Current.MainPage.Navigation.ModalStack.Count > 0)
                {
                    await Application.Current.MainPage.Navigation.PopModalAsync();
                    Console.WriteLine("Modal closed successfully.");
                }
                else
                {
                    Console.WriteLine("Modal stack is empty.");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error in CloseModalAsync: {ex.Message}");
            }
        }
    
    
        private async void DeleteDoc(object sender, EventArgs e)
        {
            bool answer = await DisplayAlert("Supprimer un document obligatoire", "Êtes-vous sûr de vouloir supprimer ce document ?", "Oui", "Non");
    
            if (answer)
            {
                if (sender is ImageButton button && button.CommandParameter is RequiredDisplay toDelete)
                {
                    try
                    {
                        _db.RequiredDisplay.Remove(toDelete);
                        await _db.SaveChangesAsync();
                        await _requiredDisplayService.DeleteTodoItemAsync(toDelete.GuidRDisplay, Constantes.URLAPI + "RequiredDisplay/");
                        RequiredDisplays.Remove(toDelete);
                    }
                    catch (DbUpdateConcurrencyException ex)
                    {
                        // Option 1: Raffraîchir l'entité depuis la base de données
                        await _db.Entry(toDelete).ReloadAsync();
    
                        // Afficher un message d'erreur à l'utilisateur
                        await DisplayAlert("Échec de la suppression", "Le document a été modifié ou supprimé par une autre transaction. Veuillez réessayer.", "OK");
    
                        // Option 2: Tentative de réexécution de la suppression après rechargement
                        // _db.RequiredDisplay.Remove(toDelete);
                        // _db.SaveChanges();
                    }
                    catch (Exception ex)
                    {
                        LogFromApp logFromApp = new LogFromApp()
                        {
                            DateCreation = DateTime.Now,
                            Intitule = "ModalRequired delete doc (UserContext ContextCurrent) " + ex.Message,
                            Trace = ex.ToString(),
                            UserInvolved = " "
                        };
    
                        await _LogService.Create(logFromApp, Constantes.URLAPILOG, true);
                        // Afficher un message d'erreur générique
                        await DisplayAlert("Erreur", "Une erreur est survenue lors de la suppression du document.", "OK");
                    }
                }
            }
        }
        private async Task ShowToasterAsync(string message)
        {
            var toast = Toast.Make(message);
            await toast.Show();
        }
    
        public async void AddDoc_Clicked(object sender, EventArgs e)
        {
            await AddDoc(sender, e);
        }
       
    }
    
  • 谢谢@SantiagoSquarzon,我担心会出现这种情况。如果您允许,我想探索一个想法。创建 2 个脚本 ~ control.ps1(定义和控制

  • Pycm 3月前 0 只看Ta
    引用 9

    是的,它编译了,可能是我忘了删除多余的'}'

  • 注意,我切换到了纯 HTML 字符串模板,效果非常好。我想我毕竟不需要 react-email 了,谢谢!

  • Juri 3月前 0 只看Ta
    引用 11

    我强烈建议您不要将 Cloud Function 中的 React 仅用于生成 HTML 电子邮件正文。引入所需的所有依赖项是疯狂的,而且您几乎肯定会陷入依赖地狱,因为许多 React 或其软件包都假设它们是在浏览器环境中执行的,而 Cloud Functions 则并非如此。

    我建议你找一些不依赖 React(或任何其他重型 UI 框架)的 NodeJS 包。也许是像 email-templates

    也许 能够让上述代码最终解决所有 TypeScript 警告/错误并安装所有正确的依赖项,但对于本质上只是对 HTML 主体进行搜索和替换的工作而言,这需要耗费大量的技术。

  • 请打开 esp 异常解码器或使用

  • 你的代码能编译吗?你的

  • 我的答案中的第一个解决方案使用数字;第二个解决方案使用字符串。第二个解决方案更容易理解和维护,这就是我推荐它的原因。如果您无法更改 BE 的工作方式,请选择解决方案 1。

  • 服务器请求一个数字,但是我可以建立一个请求接口,让 TypeScript 将其推断为响应对象,并在 js 中发送数字字段吗?

  • 你可以看一下这个 演示 :

    interface UserResponse {
        firstname: string;
        lastname: string;
        age: number;
        address: string;
        email: string;
    };
    
    const allFields = {
        1: 'firstname' as const,
        2: 'lastname' as const,
        3: 'age' as const,
        4: 'address' as const,
        5: 'email' as const
    };
    
    type AllFields = typeof allFields;
    type AllFieldsKeys = keyof AllFields;
    type ToProp<T extends number> = T extends AllFieldsKeys ? AllFields[T]: never;
    
    type FullResult = {
        [p in AllFieldsKeys as ToProp<p>] : UserResponse[ToProp<p>]
    }
    
    function server<T extends AllFieldsKeys>(fields: T[]): Pick<FullResult, ToProp<T>> {
      return fields.reduce((prev: any, curr) => {
        // In real life value will probably not be null
        return (prev as any)[curr] = null; 
      }, {});
    }
    
    const test = server([1,3,4]);
    console.log(test.address); // OK string
    console.log(test.firstname); // OK string
    console.log(test.lastname); // ERROR
    console.log(test.age); // OK number
    console.log(test.email); // ERROR
    

    笔记

    正如其他人提到的,使用数字代替属性名称可能不是一个好主意。如果使用属性名称,代码将更容易理解:

    interface AllFields {
        firstname: string;
        lastname: string;
        age: number;
        address: string;
        email: string;
    };
    
    type AllFieldsKeys = keyof AllFields;
    
    type ToProp<T extends keyof AllFields> =
        T extends AllFieldsKeys ?
            AllFields[T]: never;
    
    function server<T extends AllFieldsKeys>(fields: T[]): Pick<AllFields, T> {
      return fields.reduce((prev: any, curr) => {
         // Backend will probably return something not null
        return (prev as any)[curr] = null;
      }, {});
    }
    
    const test = server(["address","age"]);
    console.log(test.address); // OK  string
    console.log(test.firstname); // ERROR
    console.log(test.lastname); // ERROR
    console.log(test.age); // OK number
    console.log(test.email); // ERROR
    
  • 顺便说一句,他们决定使用数字来表示必填字段而不是使用实际的属性名称,这似乎很奇怪。

  • 这很奇怪。我创建了一个项目并测试了模式堆栈导航,它工作正常。尝试在执行数据库操作后添加 Task.Delay

  • @Cfun 像往常一样感谢 Stack Overflow 上的人们回答所有代码,以便理解所有含义。是的,模式堆栈是空的。我正在寻找 try catch,谢谢

  • 考虑改变 try-catch 的设计,以便在 finally 块内捕获异常

返回
作者最近主题: