澳门永利备用网址在言语的其他特色中也都有迭代器的人影,NanUI文书档案目录

NanUI文书档案目录

 前边的话

  用循环语句迭代数据时,要求求起先化一个变量来记录每二遍迭代在多少集合中的地点,而在许多编制程序语言中,已经起来通进度序化的措施用迭代器对象回来迭代进度中聚合的每1个因素

  迭代器的运用能够相当大地简化数据操作,于是ES陆也向JS中加多了那一个迭代器本性。新的数组方法和新的集合类型(如Set集结与Map群集)都正视迭代器的兑现,这几个新特点对于快捷的数据管理来讲是少不了的,在言语的别样特色中也都有迭代器的身影:新的for-of循环、张开运算符(…),以致连异步编制程序都足以行使迭代器

  本文将详细介绍ES陆中的迭代器(Iterator)和生成器(Generator)

 

引入

  上面是壹段正式的for循环代码,通过变量i来追踪colors数组的目录,循环每一次实践时,如若i小于数首席试行官度len则加1,并奉行下贰回巡回

var colors = ["red", "green", "blue"];
for (var i = 0, len = colors.length; i < len; i++) {
    console.log(colors[i]);
}

  纵然循环语句语法简单,但借使将几个巡回嵌套则需求追踪多少个变量,代码复杂度会大大扩张,一相当的大心就漏洞百出选择了别的for循环的追踪变量,从而产生程序出错。迭代器的面世意在祛除这种复杂并减弱循环中的错误

 

如何落到实处C#与Javascript的竞相通讯

透过事先的小说,相信您曾经对NanUI有了开首的摸底。但到近来停止,我们利用NanUI仅仅只是当作显示HTML分界面包车型地铁容器,并未有涉及CEF与C#间数据的相互。那么本文将简介怎么样在NanUI中使用C#调用Javascript的函数以及怎么样在Javascript注入C#的对象、属性和方法。

迭代器

  迭代器是1种特别目的,它富有部分专程为迭代经过规划的专有接口,全部的迭代器对象都有叁个next()方法,每回调用都回去2个结实对象。结果对象有三个属性:一个是value,表示下一个就要重返的值;另三个是done,它是一个布尔类型的值,当未有越来越多可回到数据时再次回到true。迭代器还可能会保留一个里边指针,用来针对当前集合中值的地点,每调用贰回next()方法,都会回去下3个可用的值

  若是在最终二个值再次来到后再调用next()方法,那么再次来到的目的中质量done的值为true,属性value则带有迭代器最后回到的值,这几个重返值不是数据集的1局地,它与函数的再次来到值类似,是函数调用进度中最终一遍给调用者传递音信的办法,如若未有有关数据则再次回到undefined

  下边用ES5的语法创设三个迭代器

function createIterator(items) {
    var i = 0;
    return {
        next: function() {
            var done = (i >= items.length);
            var value = !done ? items[i++] : undefined;
            return {
                done: done,
                value: value
            };
        }
    };
}
var iterator = createIterator([1, 2, 3]);
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: 2, done: false }"
console.log(iterator.next()); // "{ value: 3, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"
// 之后的所有调用
console.log(iterator.next()); // "{ value: undefined, done: true }"

  在地点这段代码中,createIterator()方法重回的对象有1个next()方法,每一回调用时,items数组的下三个值会作为value再次回到。当i为3时,done变为true;此时元春表明式会将value的值设置为undefined。最终一遍调用的结果与ES六迭代器的最后回到机制就如,当数码集被用尽后会再次来到最后的源委

  上边那几个示例很复杂,而在ES陆中,迭代器的编辑撰写规则也1律复杂,但ES陆同临时间还引进了贰个生成器对象,它能够让创设迭代器对象的长河变得更简便易行

 

C#调用Javascript函数

生成器

  生成器是一种回到迭代器的函数,通过function关键字后的星号(*)来表示,函数中会用到新的基本点字yield。星号能够紧挨着function关键字,也足以在中等增添1个空格

// 生成器
function *createIterator() {
    yield 1;
    yield 2;
    yield 3;
}
// 生成器能像正规函数那样被调用,但会返回一个迭代器
let iterator = createIterator();
console.log(iterator.next().value); // 1
console.log(iterator.next().value); // 2
console.log(iterator.next().value); // 3

  在那么些示例中,createlterator()前的星号注脚它是三个生成器;yield关键字也是ES6的新特征,能够通过它来钦定调用迭代器的next()方法时的再次来到值及重临顺序。生成迭代器后,延续3次调用它的next()方法重回三个不等的值,分别是一、贰和三。生成器的调用进度与其余函数同样,最终回到的是开创好的迭代器

  生成器函数最风趣的片段是,每当施行完一条yield语句后函数就能够自行终止施行。举个例子,在上边这段代码中,推行完语句yield
一之后,函数便不再实施其它任何语句,直到再度调用迭代器的next()方法才会连续实施yield
2语句。生成器函数的这种中止函数施行的本事有繁多妙不可言的利用

  使用yield关键字能够回到任何值或表明式,所以能够通过生成器函数批量地给迭代器添日币素。譬如,能够在循环中应用yield关键字

function *createIterator(items) {
    for (let i = 0; i < items.length; i++) {
        yield items[i];
    }
}
let iterator = createIterator([1, 2, 3]);
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: 2, done: false }"
console.log(iterator.next()); // "{ value: 3, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"
// 之后的所有调用
console.log(iterator.next()); // "{ value: undefined, done: true }"

  在此示例中,给生成器函数createlterator()传入一个items数组,而在函数内部,for循环不断从数组中生成新的因素放入迭代器中,每碰到2个yield语句循环都会终止;每趟调用迭代器的next()方法,循环会继续运维并奉行下一条yield语句

  生成器函数是ES陆中的2个器重特征,能够将其用来全数援助函数使用的地点

【使用限制】

  yield关键字只可在生成器内部采纳,在别的地点选择会招致程序抛出荒谬

function *createIterator(items) {
    items.forEach(function(item) {
        // 语法错误
        yield item + 1;
    });
}

  从字面上看,yield关键字实在在createlterator()函数内部,可是它与return关键字同样,二者都不能穿透函数边界。嵌套函数中的return语句无法作为外部函数的归来语句,而这边嵌套函数中的yield语句会促成程序抛出语法错误

【生成器函数表明式】

  也能够因而函数表明式来创立生成器,只需在function关键字和小括号中间增多2个星号(*)即可

let createIterator = function *(items) {
    for (let i = 0; i < items.length; i++) {
        yield items[i];
    }
};
let iterator = createIterator([1, 2, 3]);
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: 2, done: false }"
console.log(iterator.next()); // "{ value: 3, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"
// 之后的所有调用
console.log(iterator.next()); // "{ value: undefined, done: true }"

  在这段代码中,createlterator()是一个生成器函数表明式,而不是一个函数注明。由于函数表明式是无名的,因而星号直接放在function关键字和小括号之间。此外,那些示例基本与前例同样,使用的也是for循环

  [注意]不能够用箭头函数来创立生成器

【生成器对象的艺术】

  由于生成器本人正是函数,因此能够将它们增加到目的中。比如,在ES5作风的靶子字面量中,可以通过函数表明式来创制生成器

var o = {
    createIterator: function *(items) {
            for (let i = 0; i < items.length; i++) {
                yield items[i];
            }
        }
};
let iterator = o.createIterator([1, 2, 3]);

  也得以用ES陆的函数方法的简写格局来成立生成器,只需在函数名前增多贰个星号(*)

var o = {
    *createIterator(items) {
            for (let i = 0; i < items.length; i++) {
                yield items[i];
            }
        }
};
let iterator = o.createIterator([1, 2, 3]);

  这几个示例使用了分歧于以前的语法,但它们的作用实在是等价的。在简写版本中,由于不使用function关键字来定义createlterator()方法,因而就算能够在星号和办法名之间留白,但如故将星号紧贴在方法名此前

【状态机】

  生成器的三个常用成效是生成状态机

let state = function*(){
    while(1){
        yield 'A';
        yield 'B';
        yield 'C';
    }
}

let status = state();
console.log(status.next().value);//'A'
console.log(status.next().value);//'B'
console.log(status.next().value);//'C'
console.log(status.next().value);//'A'
console.log(status.next().value);//'B'

 

不要求获得再次回到值的景况

借使页面中就像下Javascript的函数sayHello,它的作用是在DOM中创设1个涵盖有“Hello
NanUI!”字样的p元素。

function sayHello() {
    var p = document.createElement("p");
    p.innerText = "Hello NanUI!";

    var container = document.getElementById("hello-container");
    container.appendChild(p);
}

身体力行中,该函数并从未在Javascript境况里调用,而是在页面加载成功后使用NanUI的ExecuteJavascript主意来调用它。ExecuteJavascript艺术试行的回到结果为贰个bool类型,它提示了本次有未能如愿实行。

在窗体的构造函数中,通过注册Formium的LoadHandler中的OnLoadEnd事件来监测页面加载成功的场所,并在页面加载成功后调用JS情状中的函数sayHello。

namespace CommunicateBetweenJsAndCSharp
{
    using NetDimension.NanUI;
    public partial class Form1 : Formium
    {
        public Form1()
            : base("http://res.app.local/www/index.html",false)
        {
            InitializeComponent();

            LoadHandler.OnLoadEnd += LoadHandler_OnLoadEnd;
        }

        private void LoadHandler_OnLoadEnd(object sender, Chromium.Event.CfxOnLoadEndEventArgs e)
        {
            // Check if it is the main frame when page has loaded.
            if(e.Frame.IsMain)
            {
                ExecuteJavascript("sayHello()");
            }
        }
    }
}

运作后,能够见见分界面中展现了“Hello
NanUI!”字样,表明使用ExecuteJavascript能够调用JS函数。


可迭代对象

  可迭代对象具有Symbol.iterator属性,是壹种与迭代器密切相关的指标。Symbol.iterator通过点名的函数能够重回贰个成效于附属对象的迭代器。在ES陆中,全体的汇集对象(数组、Set会集及Map会集)和字符串都以可迭代对象,那几个目的中都有暗中同意的迭代器。ES陆中新参加的特征for-of循环须要用到可迭代对象的这几个功效

  [注意]鉴于生成器默许会为Symbol.iterator属性赋值,因而具有通过生成器创设的迭代器都以可迭代对象

  1开始,大家曾提到过巡回之中索引跟踪的连带主题材料,要化解那几个主题素材,供给多少个工具:二个是迭代器,另2个是for-of循环。如此1来,便不必要再追踪整个集合的目录,只需关切群集中要处理的剧情

  for-of循环每实行一回都会调用可迭代对象的next()方法,并将迭代器再次回到的结果对象的value属性存款和储蓄在八个变量中,循环将处处举行这一进度直到回到对象的done属性的值为true。这里有个示范

let values = [1, 2, 3];
for (let num of values) {
    //1
    //2
    //3
    console.log(num);
}

  这段for-of循环的代码通过调用values数组的Symbol.iterator方法来获取迭代器,那壹进度是在JS引擎背后实现的。随后迭代器的next()方法被频仍调用,从其回来对象的value属性读取值并蕴藏在变量num中,依次为1、贰和三,当结果对象的done属性值为true时循环退出,所以num不会被赋值为undefined

  假诺只需迭代数组或集结中的值,用for-of循环替代for循环是个科学的抉择。相比较古板的for循环,for-of循环的垄断原则更简短,不须求追踪复杂的尺度,所以越来越少出错

  [注意]若是将for-of语句用于不可迭代对象、null或undefined将会招致程序抛出荒唐

【访问默许迭代器】

  能够经过Symbol.iterator来访问对象默许的迭代器

let values = [1, 2, 3];
let iterator = values[Symbol.iterator]();
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: 2, done: false }"
console.log(iterator.next()); // "{ value: 3, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"

  在这段代码中,通过Symbol.iterator获取了数组values的暗中认可迭代器,并用它遍历数组中的成分。在JS引擎中试行for-of循环语句时也是有近似的管理进度

  由于具备Symbol.iterator属性的靶子都有暗中同意的迭代器,因而得以用它来检测对象是否为可迭代对象

function isIterable(object) {
    return typeof object[Symbol.iterator] === "function";
}
console.log(isIterable([1, 2, 3])); // true
console.log(isIterable("Hello")); // true
console.log(isIterable(new Map())); // true
console.log(isIterable(new Set())); // true
console.log(isIterable(new WeakMap())); // false
console.log(isIterable(new WeakSet())); // false

  这里的islterable()函数能够检查钦赐对象中是否存在暗中认可的函数类型迭代器,而for-of循环在推行前也会做一般的反省

  除了利用内建的可迭代对象类型的Symbol.iterator,也得以行使Symbol.iterator来成立属于本人的迭代器

【创立可迭代对象】

  暗许景况下,开垦者定义的指标都以不足迭代对象,但借使给Symbol.iterator属性增多一个生成器,则足以将其形成可迭代对象

let collection = {
    items: [],
    *[Symbol.iterator]() {
        for (let item of this.items) {
            yield item;
        }
    }
};
collection.items.push(1);
collection.items.push(2);
collection.items.push(3);
for (let x of collection) {
    //1
    //2
    //3
    console.log(x);
}

  在那么些示例中,先成立叁个生成器(注意,星号依旧在质量名前)并将其赋值给目的的Symbol.iterator属性来创制默许的迭代器;而在生成器中,通过for-of循环迭代this.items并用yield再次回到每1个值。collection对象暗中同意迭代器的归来值由迭代器this.items自动生成,而非手动遍历来定义再次来到值

【张开运算符和非数组可迭代对象】

  通过开始展览运算符(…)能够把Set集合调换到一个数组

let set = new Set([1, 2, 3, 3, 3, 4, 5]),
array = [...set];
console.log(array); // [1,2,3,4,5]

  这段代码中的张开运算符把Set群集的具备值填充到了贰个数组字面量里,它能够操作全部可迭代对象,并依赖默许迭代器来挑选要引用的值,从迭代器读取全数值。然后遵照再次回到顺序将它们依次插入到数组中。Set集结是三个可迭代对象,张开运算符也足以用来其余可迭代对象

let map = new Map([ ["name", "huochai"], ["age", 25]]),
array = [...map];
console.log(array); // [ ["name", "huochai"], ["age", 25]]

  实行运算符把Map集结账和转账换来包蕴几个数组的数组,Map集合的暗中同意迭代器再次来到的是多组键值对,所以结果数组与实践new
Map()时传出的数组看起来同样

  在数组字面量中能够频仍用到进行运算符,将可迭代对象中的四个因素依次插入新数组中,替换原先展开运算符所在的地点

let smallNumbers = [1, 2, 3],
bigNumbers = [100, 101, 102],
allNumbers = [0, ...smallNumbers, ...bigNumbers];
console.log(allNumbers.length); // 7
console.log(allNumbers); // [0, 1, 2, 3, 100, 101, 102]

  成立三个变量allNumbers,用张开运算符将smallNumbers和bigNumbers里的值依次增加到allNumbers中。首先存入0,然后存入small中的值,最终存入bigNumbers中的值。当然,原始数组中的值只是被复制到allNumbers中,它们本人并未有改观

  由于开始展览运算符能够功用于自由可迭代对象,因而假如想将可迭代对象转变为数组,那是最简易的方法。既能够将字符串中的每2个字符(不是编码单元)存入新数组中,也能够将浏览器中NodeList对象中的每二个节点存入新的数组中

 

亟待获得再次回到值的情况

上边的事例中经过ExecuteJavascript措施来得逞调用了JS景况中的函数。但轻易开掘,这种调用形式C#是从未接受到别的再次回到值的。但实际上的项目里,大家是内需从JS境遇获得到重临值的,那时候使用ExecuteJavascript将不能满意要求,使用其它三个办法EvaluateJavascript能够援救大家从JS情况中收获JS函数的重返值。

假使有此外贰个Javascript函数sayHelloToSomeone,它能吸收接纳3个字符传参数,在函数体中拼接并重临拼接后的字符串。

function sayHelloToSomeone(who) {
    return "Hello " + who + "!";
}

一点差异也未有于的,在上头例子LoadHandler的OnLoadEnd事件中大家来进行sayHelloToSomeone,并通过C#传送参数并获取拼接后的重回值。EvaluateJavascript办法通过二个回调Action来获得JS景况中的再次回到值。那些Action有七个参数,第二个是重回值的聚众,第3个是JS情形的要命对象,假如函数正确执行,那么第二个参数为null

namespace CommunicateBetweenJsAndCSharp
{
    using NetDimension.NanUI;
    public partial class Form1 : Formium
    {
        public Form1()
            : base("http://res.app.local/www/index.html",false)
        {
            InitializeComponent();

            LoadHandler.OnLoadEnd += LoadHandler_OnLoadEnd;
        }

        private void LoadHandler_OnLoadEnd(object sender, Chromium.Event.CfxOnLoadEndEventArgs e)
        {
            // Check if it is the main frame when page has loaded.
            if(e.Frame.IsMain)
            {
                EvaluateJavascript("sayHelloToSomeone('C#')", (value, exception) =>
                {
                    if(value.IsString)
                    {
                        // Get value from Javascript.
                        var jsValue = value.StringValue;

                        MessageBox.Show(jsValue);
                    }
                });
            }
        }
    }
}

在地点的言传身教中,通过大家得以一清2楚知晓JS函数sayHelloToSomeone的重返值一定为String类型,因而在C#的回调中从来运用Value的StringValue属性来获得JS函数的字符传重回值。但在骨子里的选用中,有极大希望并不完全了解重返值的体系,由此供给使用Value中放置的①1判别属性来所有人家筛选再次回到值。

急需注意的是,Value的类是是ChromiumFX中的CfrV8Value品类,它是三个老大重要的连串,基本上全体在C#与CEF间的通讯都是由那么些种类来完毕的。


内建迭代器

  迭代器是ES六的3个主要组成部分,在ES6中,已经默以为许多内建类型提供了内建迭代器,唯有当这几个内建迭代器不可能达成目的时才需求和煦创立。经常来讲当定义自身的指标和类时才会蒙受这种状态,不然,完全能够凭仗内建的迭代器完毕专业,而最常使用的或者是汇聚的那个迭代器

【会集对象迭代器】

  在ES陆中有三种档期的顺序的集结对象:数组、Map集合与Set集结

  为了越来越好地走访对象中的内容,那三种对象都内建了以下两种迭代器

entries() 返回一个迭代器,其值为多个键值对
values() 返回一个迭代器,其值为集合的值
keys() 返回一个迭代器,其值为集合中的所有键名

  调用以上三个点子都可以访问集结的迭代器

entries()迭代器

  每一回调用next()方法时,entries()迭代器都会回去七个数组,数组中的多少个成分分别代表集结中每种成分的键与值。假诺被遍历的对象是数组,则第1个要素是数字类型的目录;借使是Set会集,则率先个元素与第二个因素都以值(Set集结中的值被同时作为键与值使用);如若是Map集合,则第二个成分为键名

let colors = [ "red", "green", "blue" ];
let tracking = new Set([1234, 5678, 9012]);
let data = new Map();
data.set("title", "Understanding ES6");
data.set("format", "ebook");
for (let entry of colors.entries()) {
    console.log(entry);
}
for (let entry of tracking.entries()) {
    console.log(entry);
}
for (let entry of data.entries()) {
    console.log(entry);
}

  调用console.log()方法后输出以下内容

[0, "red"]
[1, "green"]
[2, "blue"]
[1234, 1234]
[5678, 5678]
[9012, 9012]
["title", "Understanding ES6"]
["format", "ebook"]

  在这段代码中,调用每种会集的entries()方法获得二个迭代器,并应用for-of循环来遍历成分,且通过console将每一个对象的键值对出口出来

values()迭代器

  调用values()迭代器时会重临集合中所存的全部值

let colors = [ "red", "green", "blue" ];
let tracking = new Set([1234, 5678, 9012]);
let data = new Map();
data.set("title", "Understanding ES6");
data.set("format", "ebook");
for (let value of colors.values()) {
    console.log(value);
}
for (let value of tracking.values()) {
    console.log(value);
}
for (let value of data.values()) {
    console.log(value);
}

  调用console.log()方法后输出以下内容

"red"
"green"
"blue"
1234
5678
9012
"Understanding ES6"
"ebook"

  如上所示,调用values()迭代器后,重回的是各种集结中隐含的着实数据,而不带有数据在汇集中的地方音信

keys()迭代器

  keys()迭代器会回到集结中设有的每三个键。就算遍历的是数组,则会回来数字类型的键,数组本身的其余属性不会被再次回到;假如是Set集结,由于键与值是均等的,由此keys()和values()重回的也是同样的迭代器;若是是Map集结,则keys()迭代器会回来各种独立的键

let colors = [ "red", "green", "blue" ];
let tracking = new Set([1234, 5678, 9012]);
let data = new Map();
data.set("title", "Understanding ES6");
data.set("format", "ebook");
for (let key of colors.keys()) {
    console.log(key);
}
for (let key of tracking.keys()) {
    console.log(key);
}
for (let key of data.keys()) {
    console.log(key);
}

  调用console.log()方法后输出以下内容

0
1
2
1234
5678
9012
"title"
"format"

  keys()迭代器会获得colors、tracking和data那个汇集中的各类键,而且各自在三个for-of循环之上将这一个键名打字与印刷出来。对于数组对象的话,无论是或不是为数组增多命名属性,打字与印刷出来的都是数字类型的目录;而for-in循环迭代的是数组属性而不是数字类型的目录

昨今差别集结类型的暗中同意迭代器

  每种集结类型都有2个私下认可的迭代器,在for-of循环中,假如没有显式钦命则选取私下认可的迭代器。数组和Set集合的暗许迭代器是values()方法,Map会集的默许迭代器是entries()方法。有了这几个暗中认可的迭代器,能够更自在地在for-of循环中选择集合对象

let colors = [ "red", "green", "blue" ];
let tracking = new Set([1234, 5678, 9012]);
let data = new Map();
data.set("title", "Understanding ES6");
data.set("format", "print");
// 与使用 colors.values() 相同
for (let value of colors) {
    console.log(value);
}
// 与使用 tracking.values() 相同
for (let num of tracking) {
    console.log(num);
}
// 与使用 data.entries() 相同
for (let entry of data) {
    console.log(entry);
}

  上述代码未钦点迭代器,所以将使用暗中认可的迭代器。数组、Set集结及Map集结的暗中认可迭代器也会反射出那么些目的的初阶化进度,所以这段代码会输出以下内容

"red"
"green"
"blue"
1234
5678
9012
["title", "Understanding ES6"]
["format", "print"]

  暗中同意情况下,假如是数组和Set集结,会挨个重回群集中有着的值。如若是Map集结,则依据Map构造函数参数的格式重临同样的数组内容。而WeakSet会集与WeakMap集结就从不内建的迭代器,由于要处理弱引用,由此不可能适用地领悟集合中留存的值,也就无法迭代那么些集中了

【字符串迭代器】

  自ES5文告之后,JS字符串慢慢变得更像数组了,举个例子,ES伍正式显明能够由此方括号访问字符串中的字符(也便是说,text[0]能够博得字符串text的第四个字符,并由此及彼)。由于方括号操作的是编码单元而非字符,由此不恐怕精确访问双字节字符

var message = "A 𠮷 B" ;
for (let i=0; i < message.length; i++) {
    console.log(message[i]);
}

  在这段代码中,访问message的length属性获取索引值,并透过方括号访问来迭代并打字与印刷二个字眼符字符串,不过出口的结果却与预期不符

A




B

  由于双字节字符被视作多个单身的编码单元,从而最终在A与B之间打印出四个空行

  所幸,ES6的靶子是巨细无遗帮衬Unicode,并且大家能够透过退换字符串的默许迭代器来化解那几个题目,使其操作字符而不是编码单元。现在,修改前3个演示中字符串的暗许迭代器,让for-of循环输出准确的剧情

var message = "A 𠮷 B" ;
for (let c of message) {
    console.log(c);
}

  这段代码输出以下内容

A

𠮷

B

  那个结果更符合预期,通过循环语句能够一贯操作字符并成功打字与印刷出Unicode字符

【NodeList迭代器】

  DOM规范中有2个NodeList类型,document对象中的全部因素都用这几个连串来表示。对于编写Web浏览器蒙受中的JS开拓者来讲,须求花点儿武功去领略NodeList对象和数组之间的出入。二者都利用length属性来代表集结巧月素的多少,都能够通过方括号来访问集合中的独立成分。而在里面贯彻中,二者的突显不行不一样等,由此会促成大多劳神

  自从ES6增多了暗中认可迭代器后,DOM定义中的NodeList类型(定义在HTML规范而不是ES6正规中)也具有了暗中同意迭代器,其行事与数组的私下认可迭代器完全壹致。所以能够将NodeList应用于for-of循环及任何帮衬对象暗中同意迭代器的地点

var divs = document.getElementsByTagName("div");
for (let div of divs) {
    console.log(div.id);
}

  在这段代码中,通过调用getElementsByTagName()方法获得到document对象中全部div成分的列表,在for-of循环中遍历列表中的每2个成分并出口元素ID,实际上是根据拍卖数组的艺术来管理NodeList的

 

Javascript调用C#对象及办法

高端迭代器

  迭代器的底蕴成效能够扶助达成繁多职分,通过生成器创制迭代器的经过也很轻松,除了那一个归纳的联谊遍历职分之外,迭代器也能够被用于完结都部队分目不暇接的天职

【给迭代器传递参数】

  迭代器既能够用迭代器的next()方法再次来到值,也能够在生成器内部选拔yield关键字来生成值。假诺给迭代器的next()方法传递参数,则那一个参数的值就能够代替生成器内部上条yield语句的重临值。而倘使要兑现愈来愈多像异步编制程序那样的高端作用,那么这种给迭代器传值的技术就变得至关心注重要

function *createIterator() {
    let first = yield 1;
    let second = yield first + 2; // 4 + 2
    yield second + 3; // 5 + 3
}
let iterator = createIterator();
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next(4)); // "{ value: 6, done: false }"
console.log(iterator.next(5)); // "{ value: 8, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"

  第叁回调用next()方法时无论传入什么参数都会被遗弃。由于传给next()方法的参数会代替上壹遍yield的再次回到值,而在率先次调用next()方法前不会实施任何yield语句,由此在第二回调用next()方法时传递参数是毫无意义的

  第壹遍调用next()方法传入数值4作为参数,它最后被赋值给生成器函数内部的变量first。在二个含参yield语句中,表达式左侧等价于首回调用next()方法后的下3个重临值,表明式左边等价于第1次调用next()方法后,在函数继续实践前猎取的再次来到值。第三回调用next()方法传入的值为四,它会被赋值给变量first,函数则继续试行。第2条yield语句在第贰回yield的结果上加了二,最后的重临值为六

  首回调用next()方法时,传入数值伍,那几个值被赋值给second,最终用于第1条yield语句并最终回到数值八

【在迭代器中抛出荒唐】  

  除了给迭代器传递数据外,还足以给它传递错误条件。通过throw()方法,当迭代器苏醒实行时可令其抛出三个谬误。这种积极抛出错误的能力对于异步编制程序来讲重要性,也能提供模拟截止函数施行的二种格局(重返值或抛出错误),从而加强生成器内部的编制程序弹性。将错误对象传给throw()方法后,在迭代器继续实施时其会被抛出

function *createIterator() {
    let first = yield 1;
    let second = yield first + 2; // yield 4 + 2 ,然后抛出错误
    yield second + 3; // 永不会被执行
}
let iterator = createIterator();
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next(4)); // "{ value: 6, done: false }"
console.log(iterator.throw(new Error("Boom"))); // 从生成器中抛出了错误

  在那些示例中,前八个说明式不荒谬求值,而调用throw()方法后,在继续实施let
second求值前,错误就能被抛出并阻碍了代码继续实行。那个进度与直接抛出荒唐很相像,2者唯壹的界别是抛出的时机不如

  能够在生成器内部通过try-catch代码块来捕获这一个不当

function *createIterator() {
    let first = yield 1;
    let second;
    try {
        second = yield first + 2; // yield 4 + 2 ,然后抛出错误
    } catch (ex) {
        second = 6; // 当出错时,给变量另外赋值
    }
    yield second + 3;
}
let iterator = createIterator();
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next(4)); // "{ value: 6, done: false }"
console.log(iterator.throw(new Error("Boom"))); // "{ value: 9, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"

  在此示例中,try-catch代码块包裹着第1条yield语句。就算那条语句笔者并未有不当,但在给变量second赋值前依然会继续努力抛出荒唐,catch代码块捕获错误后将second变量赋值为陆,下一条yield口舌继续施行后重返玖

  这里有三个有趣的地方调用throw()方法后也会像调用next()方法同样再次来到八个结果对象。由于在生成器内部捕获了那些荒唐,因此会继续推行下一条yield说话,最后回到数值九

  如此1来,next()和throw()就像是迭代器的两条指令,调用next()方法命令迭代器继续施行(也许提供2个值),调用throw()方法也会命令迭代器继续实践,但与此同有的时候候也抛出一个指鹿为马,在此之后的实践进程取决于生成器内部的代码

  在迭代器内部,纵然选择了yield语句,则足以由此next()方法和throw()方法调整奉行进度,当然,也得以应用return语句重返一些与平常函数再次来到语句不太同样的从头到尾的经过

【生成器重临语句】

  由于生成器也是函数,由此得以因而return语句提前退出函数试行,对于最终贰遍next()方法调用,能够主动为其内定3个重返值。正如在其余函数中那样,能够透过return语句钦定二个重返值。而在生成器中,return代表全部操作已经产生,属性done棉被服装置为true;假设同不经常常候提供了对应的值,则属性value会被设置为那么些值

function *createIterator() {
    yield 1;
    return;
    yield 2;
    yield 3;
}
let iterator = createIterator();
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"

  这段代码中的生成器包含多条yield语句和一条return语句,当中return语句紧随第叁条yield语句,其后的yield语句将不会被施行

  在return语句中也得以钦命八个再次回到值,该值将被赋值给重回对象的value属性

function *createIterator() {
    yield 1;
    return 42;
}
let iterator = createIterator();
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: 42, done: true }"
console.log(iterator.next()); // "{ value: undefined, done: true }"

  在此示例中,首回调用next()方法时再次来到对象的value属性值为4二,done属性第一回设为true;第2遍调用next()方法照旧重返3个对象,只是value属性的值会变为undefined。因而,通过return语句钦命的重回值,只会在回来对象中出现三回,在三番五次调用再次来到的对象中,value属性会被重新恢复设置为undefined

  [注意]进展运算符与for-of循环语句会一向忽略通过return语句钦点的别样重回值,只要done1变为true就应声终止读取别的的值。不管怎样,迭代器的再次回到值还是是2个可怜有效的特色

【委托生成器】

  在好几景况下,大家供给将多个迭代器合贰为1,那时能够创造三个生成器,再给yield语句增添1个星号,就足以将转换数据的长河委托给其余生成器。当定义那个生成器时,只需将星号放置在重中之重字yield和生成器的函数名以内就可以

function *createNumberIterator() {
    yield 1;
    yield 2;
}
function *createColorIterator() {
    yield "red";
    yield "green";
}
function *createCombinedIterator() {
    yield *createNumberIterator();
    yield *createColorIterator();
    yield true;
}
var iterator = createCombinedIterator();
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: 2, done: false }"
console.log(iterator.next()); // "{ value: "red", done: false }"
console.log(iterator.next()); // "{ value: "green", done: false }"
console.log(iterator.next()); // "{ value: true, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"

  这里的生成器createCombinedIterator()先后委托了别的七个生成器createNumberlterator()和createColorlterator()。仅依照迭代器的重回值来看,它就像一个完整的迭代器,能够扭转全数的值。每三遍调用next()方法就能够委托相应的迭代器生成对应的值,直到最终由createNumberlterator()和cpeateColorlterator()创制的迭代器相当的小概回到越来越多的值,此时举办最终一条yield语句并赶回true

  有了生成器委托这么些新功用,能够尤其应用生成器的再次来到值来拍卖复杂职务

function *createNumberIterator() {
    yield 1;
    yield 2;
    return 3;
}
function *createRepeatingIterator(count) {
    for (let i=0; i < count; i++) {
        yield "repeat";
    }
}
function *createCombinedIterator() {
    let result = yield *createNumberIterator();
    yield *createRepeatingIterator(result);
}
var iterator = createCombinedIterator();
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: 2, done: false }"
console.log(iterator.next()); // "{ value: "repeat", done: false }"
console.log(iterator.next()); // "{ value: "repeat", done: false }"
console.log(iterator.next()); // "{ value: "repeat", done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"

  在生成器createCombinedlterator()中,实践进程先被信托给了生成器createNumberlterator(),再次来到值会被赋值给变量result,实践到return
3时会回来数值三。这几个值随后被传到createRepeatinglterator()作为它的参数,因此生成字符串”repeat”的yield语句会被推行二次

  无论通过何种方式调用迭代器next()方法,数值叁都不会被重临,它只设有于生成器createCombinedlterator()的里边。但假如想出口那么些值,则足以附加增多一条yield语句

function *createNumberIterator() {
    yield 1;
    yield 2;
    return 3;
}
function *createRepeatingIterator(count) {
    for (let i=0; i < count; i++) {
        yield "repeat";
    }
}
function *createCombinedIterator() {
    let result = yield *createNumberIterator();
    yield result;
    yield *createRepeatingIterator(result);
}
var iterator = createCombinedIterator();
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: 2, done: false }"
console.log(iterator.next()); // "{ value: 3, done: false }"
console.log(iterator.next()); // "{ value: "repeat", done: false }"
console.log(iterator.next()); // "{ value: "repeat", done: false }"
console.log(iterator.next()); // "{ value: "repeat", done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"

  此处新扩充长的yield语句显式地出口了生成器createNumberlterator()的重回值。

  [注意]yield*也可向来动用于字符串,举个例子yield*
“hello”,此时将运用字符串的暗中认可迭代器

 

一句话来讲的利用示范

上面的作品中示范了何等用C#来调用Javascript中的函数,那么上面包车型地铁剧情将介绍怎么着选择Javascript来调用C#中的对象、属性和种种法子。

此前,须要介绍NanUI窗体基类Formium中的主要性质GlobalObject,您能够把他通晓成Javascript意况中的window指标。假诺您须要在Javascript景况下使用C#中的种种对象、属性和办法,都亟待将这个目标、属性、方法注册到GlobalObject里。

上边包车型大巴例子,通过在Form一的构造函数中注册贰个名字为my的JS对象,并在my内置3个只读属性name,以及showCSharpMessageBoxgetArrayFromCSharpgetObjectFromCSharp两个函数。

//register the "my" object
var myObject = GlobalObject.AddObject("my");

//add property "name" to my, you should implemnt the getter/setter of name property by using PropertyGet/PropertySet events.
var nameProp = myObject.AddDynamicProperty("name");
nameProp.PropertyGet += (prop, args) =>
{
    // getter - if js code "my.name" executes, it'll get the string "NanUI". 
    args.Retval = CfrV8Value.CreateString("NanUI");
    args.SetReturnValue(true);
};
nameProp.PropertySet += (prop, args) =>
{
    // setter's value from js context, here we do nothing, so it will store or igrone by your mind.
    var value = args.Value;
    args.SetReturnValue(true);
};


//add a function showCSharpMessageBox
var showMessageBoxFunc = myObject.AddFunction("showCSharpMessageBox");
showMessageBoxFunc.Execute += (func, args) =>
{
    //it will be raised by js code "my.showCSharpMessageBox(`some text`)" executed.
    //get the first string argument in Arguments, it pass by js function.
    var stringArgument = args.Arguments.FirstOrDefault(p => p.IsString);

    if (stringArgument != null)
    {
        MessageBox.Show(this, stringArgument.StringValue, "C# Messagebox", MessageBoxButtons.OK, MessageBoxIcon.Information);


    }
};

//add a function getArrayFromCSharp, this function has an argument, it will combind C# string array with js array and return to js context.
var friends = new string[] { "Mr.JSON", "Mr.Lee", "Mr.BONG" };

var getArrayFromCSFunc = myObject.AddFunction("getArrayFromCSharp");

getArrayFromCSFunc.Execute += (func, args) =>
{
    var jsArray = args.Arguments.FirstOrDefault(p => p.IsArray);



    if (jsArray == null)
    {
        jsArray = CfrV8Value.CreateArray(friends.Length);
        for (int i = 0; i < friends.Length; i++)
        {
            jsArray.SetValue(i, CfrV8Value.CreateString(friends[i]));
        }
    }
    else
    {
        var newArray = CfrV8Value.CreateArray(jsArray.ArrayLength + friends.Length);

        for (int i = 0; i < jsArray.ArrayLength; i++)
        {
            newArray.SetValue(i, jsArray.GetValue(i));
        }

        var jsArrayLength = jsArray.ArrayLength;

        for (int i = 0; i < friends.Length; i++)
        {
            newArray.SetValue(i + jsArrayLength, CfrV8Value.CreateString(friends[i]));
        }


        jsArray = newArray;
    }


    //return the array to js context

    args.SetReturnValue(jsArray);

    //in js context, use code "my.getArrayFromCSharp()" will get an array like ["Mr.JSON", "Mr.Lee", "Mr.BONG"]
};

//add a function getObjectFromCSharp, this function has no arguments, but it will return a Object to js context.
var getObjectFormCSFunc = myObject.AddFunction("getObjectFromCSharp");
getObjectFormCSFunc.Execute += (func, args) =>
{
    //create the CfrV8Value object and the accssor of this Object.
    var jsObjectAccessor = new CfrV8Accessor();
    var jsObject = CfrV8Value.CreateObject(jsObjectAccessor);

    //create a CfrV8Value array
    var jsArray = CfrV8Value.CreateArray(friends.Length);

    for (int i = 0; i < friends.Length; i++)
    {
        jsArray.SetValue(i, CfrV8Value.CreateString(friends[i]));
    }

    jsObject.SetValue("libName", CfrV8Value.CreateString("NanUI"), CfxV8PropertyAttribute.ReadOnly);
    jsObject.SetValue("friends", jsArray, CfxV8PropertyAttribute.DontDelete);


    args.SetReturnValue(jsObject);

    //in js context, use code "my.getObjectFromCSharp()" will get an object like { friends:["Mr.JSON", "Mr.Lee", "Mr.BONG"], libName:"NanUI" }
};

运作品种开荒CEF的DevTools窗口,在Console中输入my,就能够见到my指标的详细新闻。

澳门永利备用网址 1

执行my.showCSharpMessageBox(“SOME TEXT FROM
JS”)
命令,将调用C#的MessageBox来具体JS函数中提供的“SOME TEXT FROM
JS”字样。

执行my.getArrayFromCSharp()能够从C#中取到大家松手的字符串数组中的多少个字符串。假诺在函数中内定了一个数组作为参数,那么钦定的那一个数组将和C#的字符串数组合并。

> my.getArrayFromCSharp()
["Mr.JSON", "Mr.Lee", "Mr.BONG"]

> my.getArrayFromCSharp(["Js_Bison", "Js_Dick"])
["Js_Bison", "Js_Dick", "Mr.JSON", "Mr.Lee", "Mr.BONG"]

执行my.getObjectFromCSharp()能够从C#归来大家拼装的目的,该对象有多个字符型的libName性格,以及贰个字符串数组friends

> my.getObjectFromCSharp()
Object {libName: "NanUI", friends: Array(3)}

异步任务推行

  生成器令人高兴的性状多与异步编制程序有关,JS中的异步编制程序有利有弊:轻巧任务的异步化非常轻松;而复杂任务的异步化会推动很多管制代码的挑衅。由于生成器援助在函数中间断代码实行,因此能够深切开掘异步管理的越多用法

  试行异步操作的守旧格局一般是调用三个函数并执行相应回调函数

let fs = require("fs");
fs.readFile("config.json", function(err, contents) {
    if (err) {
        throw err;
    }
    doSomethingWith(contents);
    console.log("Done");
});

  调用fs.readFile()方法时要求传入要读取的公文名和二个回调函数,操作甘休后会调用该回调函数并检讨是或不是存在不当,假若未有就足以处理回来的始末。如若要奉行的职责非常少,那么那样的办法得以很好地做到职责;要是必要嵌套回调或系列化一层层的异步操作,事情会变得极度复杂。此时,生成器和yield语句就派上用场了

【轻巧职务试行器】

  由于施行yield语句会暂停当前函数的实行进度并听候下三回调用next()方法,由此得以创制多个函数,在函数中调用生成器生成相应的迭代器,从而在毫无回调函数的底蕴上落到实处异步调用next()方法

function run(taskDef) {
    // 创建迭代器,让它在别处可用
    let task = taskDef();
    // 启动任务
    let result = task.next();
    // 递归使用函数来保持对 next() 的调用
    function step() {
        // 如果还有更多要做的
        if (!result.done) {
            result = task.next();
            step();
        }
    }
    // 开始处理过程
    step();
}

  函数run()接受2个生成器函数作为参数,那些函数定义了承接要实践的天职,生成1个迭代器并将它积攒在变量task中。第一回调用迭代器的next()方法时,再次来到的结果被储存起来稍后继续行使。step()函数会检讨result.done的值,如若为false则实行迭代器的next()方法,并再次施行step()操作。每便调用next()方法时,重临的流行消息总会覆写变量result。在代码的终极,开端化实行step()函数并开端全方位的迭代过程,每便经过检查result.done来明显是或不是有更加多职分须要施行

  借助这些run()函数,能够像那样进行贰个富含多条yield语句的生成器

run(function*() {
    console.log(1);
    yield;
    console.log(2);
    yield;
    console.log(3);
});

  那一个示例最后会向调整台出口数次调用next()方法的结果,分别为数值壹、二和三。当然,简单输出迭代次数不足以显示迭代器高档功效的实用之处,下一步就要迭代器与调用者之间彼此传值

【向任务执行器传递数据】

  给任务施行器传递数据的最简便方法是,将值通过迭代器的next()方法传入作为yield的生成值供下一次调用。在这段代码中,只需将result.value传入next()方法就能够

function run(taskDef) {
    // 创建迭代器,让它在别处可用
    let task = taskDef();
    // 启动任务
    let result = task.next();
    // 递归使用函数来保持对 next() 的调用
    function step() {
        // 如果还有更多要做的
        if (!result.done) {
            result = task.next(result.value);
            step();
        }
    }
    // 开始处理过程
    step();
}

  现在result.value作为next()方法的参数被传播,那样就能够在yield调用之间传递数据了

run(function*() {
    let value = yield 1;
    console.log(value); // 1
    value = yield value + 3;
    console.log(value); // 4
});

  此示例会向调节台出口八个数值1和4。个中,数值一取自yield
一语句中回传给变量value的值;而肆取自给变量value加三后回传给value的值。未来数量已经能够在yield调用间相互传送了,只需叁个微细改造便能扶助异步调用

【异步任务推行器】

  以前的言传身教只是在多个yield调用间来回传递静态数据,而等待3个异步进度有个别差别。任务实施器须要明白回调函数是何许以及怎么着运用它。由于yield表明式会将值重回给义务施行器,全数的函数调用都会回到叁个值,因此在某种程度上那也是几个异步操作,职责实行器会一贯等候直到操作完结

  上边定义2个异步操作

function fetchData() {
    return function(callback) {
        callback(null, "Hi!");
    };
}

  本示例的本心是让任务实践器调用的具有函数都回来一个得以实践回调进度的函数,此处fetchData()函数的再次回到值是2个可接受回调函数作为参数的函数,当调用它时会传入3个字符串”Hi!”作为回调函数的参数并执行。参数callback需求经过任务施行器内定,以保障回调函数实行时得以与底层迭代器准确交互。固然fetchData()是同台函数,但归纳增添多个延缓方法即可将其成为异步函数

function fetchData() {
    return function(callback) {
        setTimeout(function() {
            callback(null, "Hi!");
        }, 50);
    };
}

  在那一个本子的fetchData()函数中,让回调函数延迟了50ms再被调用,所以这种形式在同步和异步状态下都运作优异。只需保险每种要通过yield关键字调用的函数都遵从与之同样的形式编写

  精晓了函数中异步进程的周转格局,能够将职分实行器稍作修改。当result.value是二个函数时,任务试行器会先执行这么些函数再将结果传到next()方法

function run(taskDef) {
    // 创建迭代器,让它在别处可用
    let task = taskDef();
    // 启动任务
    let result = task.next();
    // 递归使用函数来保持对 next() 的调用
    function step() {
        // 如果还有更多要做的
        if (!result.done) {
            if (typeof result.value === "function") {
                result.value(function(err, data) {
                    if (err) {
                        result = task.throw(err);
                        return;
                    }
                    result = task.next(data);
                    step();
                });
            } else {
                result = task.next(result.value);
                step();
            }
        }
    }
    // 开始处理过程
    step();
}

  通过===操作符检査后,假若result.value是一个函数,会传出二个回调函数作为参数调用它,回调函数遵循Node.js有关推行错误的预约:全体希望的一无可取放在第三个参数(err)中,结果放在第1个参数中。借使传入了err,意味着实行进程中生出了不当,那时通过task.throw()精确输出错误对象;假若没错误产生,data被传到task.next()作为结果储存起来,并继续实行step()。假诺result.value不是叁个函数,则直接将其扩散next()方法

  以后,那么些新版的职务实践器已经能够用于全体的异步职务了。在Node.js蒙受中,若是要从文件中读取一些数目,要求在fs.readFile()外围创制贰个包装器(wrapper),并回到二个与fetchData()类似的函数

let fs = require("fs");
    function readFile(filename) {
        return function(callback) {
            fs.readFile(filename, callback);
        };
}

  readFile()接受四个文本名作为参数,再次来到三个足以奉行回调函数的函数。回调函数被平素传入fs.readFile()方法,读取实现后会实施它

run(function*() {
    let contents = yield readFile("config.json");
    doSomethingWith(contents);
    console.log("Done");
});

  在这段代码中未有别的回调变量,异步的readFile()操作却平常执行,除了yield关键字外,别的代码与一同代码毫无二致,只但是函数实行的是异步操作。所以根据平等的接口,可以编写制定一些读起来像是同步代码的异步逻辑

  当然,这几个示例中选拔的形式也是有欠缺,也就是不能够百分百确认函数中回到的别样函数一定是异步的。着重当下,最关键的是能了解职分施行进度背后的理论知识

 

回调函数

回调函数是Javascript里面根本和常用的效用,假若您在JS遭逢中登记的不二等秘书籍具备函数型的参数(即回调函数),通过Execute事件的Arguments能够拿走回调的function,并使用CfrV八Value的ExecuteFunction来推行回调。

//add a function with callback function

var callbackTestFunc = GlobalObject.AddFunction("callbackTest");
callbackTestFunc.Execute += (func,args)=> {
    var callback = args.Arguments.FirstOrDefault(p => p.IsFunction);
    if(callback != null)
    {
        var callbackArgs = CfrV8Value.CreateObject(new CfrV8Accessor());
        callbackArgs.SetValue("success", CfrV8Value.CreateBool(true), CfxV8PropertyAttribute.ReadOnly);
        callbackArgs.SetValue("text", CfrV8Value.CreateString("Message from C#"), CfxV8PropertyAttribute.ReadOnly);

        callback.ExecuteFunction(null, new CfrV8Value[] { callbackArgs });
    }
};

在Console中执行callbackTest(function(result){ console.log(result);
})
将实践无名氏回调,并取得到C#回传的result对象。

> callbackTest(function(result){ console.log(result); })
Object {success: true, text: "Message from C#"}

在大部气象下,在Javascript中回调都以因为试行了一些异步的操作,那么只要这么些异步的操作是在C#试行也是可行的,只是实现起来就相比较复杂。下边将演示怎么样促成1个异步回调。

//add a function with async callback
var asyncCallbackTestFunc = GlobalObject.AddFunction("asyncCallbackTest");
asyncCallbackTestFunc.Execute += async (func, args) => {
//save current context
var v8Context = CfrV8Context.GetCurrentContext();
var callback = args.Arguments.FirstOrDefault(p => p.IsFunction);

//simulate async methods.
await Task.Delay(5000);

if (callback != null)
{
    //get render process context
    var rc = callback.CreateRemoteCallContext();

    //enter render process
    rc.Enter();

    //create render task
    var task = new CfrTask();
    task.Execute += (_, taskArgs) =>
    {
        //enter saved context
        v8Context.Enter();

        //create callback argument
        var callbackArgs = CfrV8Value.CreateObject(new CfrV8Accessor());
        callbackArgs.SetValue("success", CfrV8Value.CreateBool(true), CfxV8PropertyAttribute.ReadOnly);
        callbackArgs.SetValue("text", CfrV8Value.CreateString("Message from C#"), CfxV8PropertyAttribute.ReadOnly);

        //execute callback
        callback.ExecuteFunction(null, new CfrV8Value[] { callbackArgs });


        v8Context.Exit();

        //lock task from gc
        lock (task)
        {
            Monitor.PulseAll(task);
        }
    };

    lock (task)
    {
        //post task to render process
        v8Context.TaskRunner.PostTask(task);
    }

    rc.Exit();

    GC.KeepAlive(task);
}

在Console中执行asyncCallbackTest(function(result){
console.log(result);
})
将施行佚名回调,大致伍秒后得到到C#回传的result对象。

> asyncCallbackTest(function(result){ console.log(result); })
Object {success: true, text: "Message from C#"}

如上,您已经轻易询问了应用NanUI如何是好到C#和Javascript的互动通讯。NanUI基于开源项目ChromiumFX开辟,由此C#与Javascript的互相与ChomiumFX保持一致,假如急需开辟尤其复杂的职能,请自行检索和参谋ChromiumFX的连锁API及示范。

身体力行源码

git clone https://github.com/NetDimension/NanUI-Examples-04-Communicate-Between-CSharp-And-JS.git

社会群众体育和增派

GitHub
https://github.com/NetDimension/NanUI/

交流群QQ群
521854872

支持我

若果你欢腾本身的劳作,并且期待NanUI持续的进化,请对NanUI项目张开帮衬以此来鼓励和帮衬本身继续NanUI的支出工作。你能够应用微信或者支付宝来围观上边包车型大巴2维码进行辅助。

澳门永利备用网址 2