-4

问题的本质

我问这个问题的真正原因——不是因为我想解决我的问题。我想知道如何在 JavaScript 中处理任务。我不需要线程并行和其他东西。计算有两个部分:IO 和 CPU。我想让 CPU 计算在 ajax 请求发送和 ajax 请求从服务器获得答案之间及时工作。有一个障碍:我从一个函数运行许多任务,这个函数必须产生任务,等待所有运行的任务,处理它们的结果并返回一些值。这就是我想要的。当然,如果您发布另一种方法来解决我的问题,我会为您的答案投票,如果没有关于任务的其他答案,我可以将其设置为解决方案。

为什么我描述我的问题,而不仅仅是询问任务?问那些前一段时间忽略并关闭这个问题的人。

问题

我的问题:我想在 JavaScript 中遍历一棵树以找到可能的最小解析。我有一个以trie形式存储的单词字典。当用户给出输入字符串时,我需要获取与输入字符串匹配的单词数,并且是单词的最短组合。

例子:

  1. 我的字典包含这些词:my, code, js, myj, scode
  2. 用户类型myjscode
  3. 我遍历我的单词树并发现输入匹配myj + scode并且my + js + code
  4. 由于第一次解析最短,所以我的函数返回2(最短解析中的单词数)

我的问题

我的字典树很大,所以我无法完全加载它。为了解决这个问题,我想做一些延迟加载。树的每个节点要么已加载并指向子节点,要么尚未加载并包含指向要加载的数据的链接。

所以,我需要在遍历树时进行节点查找调用。由于这些调用是异步的,我希望能够在加载树节点时探索其他遍历。这将改善用户的响应时间。

我想如何解决这个问题:

我的查找函数将返回一个任务。我可以调用该任务并获得其结果。一旦我遍历到加载的节点,我就可以多次调用加载子节点,每次调用都会返回一个任务。由于这些“任务”是单独的功能位,因此我可以将它们排队并在等待 ajax 调用返回时执行它们。

所以,我想知道我可以使用哪个库,或者我如何在 javascript 中模拟任务(我正在考虑 C# 中存在的任务)。

有限制:没有服务器端代码,只有 ajax 到 javascript 中的预编译字典。为什么?它必须用作密码复杂性检查器。

4

2 回答 2

2

你在你的问题中说:

当然,如果您发布另一种方法来解决我的问题,我会为您的答案投票,如果没有关于任务的其他答案,我可以将其设置为解决方案。

好的; 抱歉,但我认为 c# 风格的任务在这里不是正确的解决方案。

我会接受(尽管我认为这不正确)您的断言,即出于安全原因您必须在客户端完成所有操作。顺便说一句,我是否可以指出,如果您害怕有人窥探(因为您有安全漏洞),那么传递大量对部分密码的请求与传递一个请求一样不安全?对不起,我似乎未经同意就这样做了!

尽管如此,我将尝试用一个粗略的大纲来回答,如果你确实必须用 JavaScript 来解决你的问题,我将如何解决它;我会使用承诺。具体来说,可能是 jQuery 的 Deferred 实现。我将在这里给出一个非常粗略的伪代码大纲。

概述

你从一个结构良好的 Trie 开始。使用递归,我将构建一个结构良好的“解决方案树”,它是一个嵌套的数组数组;这将提供能够以特定消息响应用户的灵活性......但是,由于您似乎准备失去该奖金并且只想要一个数字作为解决方案,我将概述一个稍微简单的方法,您可以,如果需要,适应形式的返回数组(来自您的示例):

[["myj"],["scode"],["my"],["js"],["code"]]

我在这里也提到了这种结构,部分原因是它有助于解释我采用的方法。

笔记

我将在您的 Trie 中引用“nodes”和“valueNodes”。我认为“节点”是任何东西,而“值节点”是具有值的节点。

递归 promiseToResolveRemainder 将解析 0 表示“无法做到”;如果出现问题(例如,网络服务不可用),它只会拒绝承诺。

狡猾,hacky,未经测试的伪代码

var minDepth=0; //Zero value represents failure to match (Impossible?  Not if you are accepting unicode passwords!)

function promiseToResolveRemainder(remainder,fragmentSoFar){
    deferred = new jQuery.Deferred();
    nextChar = remainder.substring(0,1);
    if (remainder.length==1){
      //Insert code here to:
      //Test for fragmentSoFar+nextChar being a valueNode.
      //If so, resolve(1)... otherwise resolve(0)
      //!!Note that, subtly, this catches the case where fragmentSoFar is an empty string :)
      return;
    }
    remainder = remainder.substring(1);
    promiseToFindValueNode(fragmentSoFar+nextChar).then(
       function(success){
           //We know that we *could* terminate the growing fragment here and proceed
           //But we could also proceed from here by adding to the fragment
           var firstPathResolvedIn = 0;
           var secondPathResolvedIn = 0;
           promiseToResolveRemainder(remainder,'').then(
               function(resolvedIn){
                   firstPathResolvedIn = resolvedIn + 1;
               }
           ).then(
               promiseToResolveRemainder(remainder,fragmentSoFar+nextChar).then(
                   function(resolvedIn){
                       secondPathResolvedIn = resolvedIn;
                       if(!firstPathResolvedIn==0 and !secondPathResolvedIn==0){
                           deffered.resolve(Math.min(firstPathResolvedIn,secondPathResolvedIn));
                       }
                       deferred.resolve(Math.max(firstPathResolvedIn,secondPathResolvedIn));//Sloppy, but promises cannot be resolved twice, so no sweat (I know, that's a *dirty* trick!)
                   }
               )
           )
       },
       function(failure){
           //We know that we *need* at least a node or this call to
           //promiseToResolveRemainder at this iteration has been a failure.
           promiseToFindNode(fragmentSoFar+nextChar).then(
               function(resolvedIn){
                   //ok, so we *could* proceed from here by adding to the fragment
                   promiseToResolveRemainder(remainder,fragmentSoFar+nextChar).then(
                       function(resolvedIn){
                           deferred.resolve(resolvedIn);
                       }
                   )
               },
               function(failedBecause){
                   //ooops!  We've hit a dead end, we can't complete from here.
                   deferred.resolve(0);
               }
           )
       },
    )
    return deferred.Promise();
}

我对这种未经测试的笨拙的代码尝试并不特别自豪(而且我不打算为你编写解决方案!),但我为这种方法感到自豪,并相信它将产生一个健壮、可靠和高效的解决方案你的问题。不幸的是,您似乎依赖于很多webService 调用......因此,我很想抽象出对 webService 的任何调用并首先通过本地缓存检查它们。

于 2013-07-17T15:47:43.283 回答
0

不确定这是您正在寻找的,但您可以尝试 WebWorkers。

一个简单的示例位于:https ://github.com/afshinm/50k ,但您可以通过 Google 搜索更多信息。

注意 - 网络工作者将高度依赖浏览器,并且不会在机器上的单独任务中运行。

于 2013-07-16T02:28:22.733 回答