Saturday, February 22, 2014

Jint tutorial 004 - Exporting a C# Asynchronous API to the JavaScript world (Part I)

Reminder : Jint is a Javascript v 5 interpreter for the .NET Framework/Mono/Xamarin allowing to execute scripts in C# applications on Windows, MacOS, iOS, Android and Linux (Anywhere there is a C# 4.x compiler).

This tutorial demonstrates how to write an asynchronous API and export it to the javaScript world.

In this part I, I just want to show the JavaScript and C# syntax and how to handle a callback function. For now everything execute in one thread and the method read() is blocking.

In a second post I will implement a concept of main UI thread and a background thread, where the method read(), will return right away, the background thread will execute the operation and call the callback function in the context of the main thread. This pattern is well suited for for Windows and iOS.

So for now it just about how to pass a JavaScript function as a parameter of a C# method and how from C# call the method.
       
    public class Storage
    {
        private string GetFileName()
        {
            return string.Format(@"{0}\Storage.txt", Environment.GetEnvironmentVariable("TEMP"));
        }
        public void save(string text)
        {
            System.IO.File.WriteAllText(this.GetFileName(), text);
        }
        /// <summary>
        /// Synchronous version
        /// </summary>
        /// <returns></returns>
        public string read()
        {
            return this.read(null);
        }
        /// <summary>
        /// Asynchronous version. The function return null but will call the callback function
        /// when the read operation is done
        /// </summary>
        /// <param name="callBackFunction"></param>
        /// <returns></returns>
        public string read(Func<Jint.Native.JsValue, Jint.Native.JsValue[], Jint.Native.JsValue> callBackFunction)
        {
            if (callBackFunction == null)
            {
                return System.IO.File.ReadAllText(this.GetFileName());
            }
            else
            {
                var value = System.IO.File.ReadAllText(this.GetFileName()); // Execute the read operation
                Jint.Native.JsValue r = callBackFunction.Invoke( // Call the callback function
                    JsValue.Undefined,  // Pass this as undefined
                    new List<JsValue>() { value }.ToArray() // Pass the parameter data
                    );
                return null;
            }
        }
    }
    
    class Program
    {
        static Jint.Engine _engine;

        public static void Print(object s)
        {
            if (s == null) 
                s = "null";
            Console.WriteLine(s.ToString());
        }

        private static Jint.Engine CreateEngine()
        {
            var engine = new Engine();
            engine.SetValue("storage", new Storage());
            engine.SetValue("print", new Action<object>(Print));
            return engine;
        }

        static void Main(string[] args)
        {
            var source = @"

                storage.save('Hello World I');
                
                storage.read(function(data) { // Using callback function
                    print('read:'+data);
                });
            ";
            CreateEngine().Execute(source);
            Console.ReadLine();
        }
    }

No comments:

Post a Comment