打字稿:将图像向左移动,然后向右移动

时间:2017-07-18 17:32:14

标签: javascript typescript callback

第一个免责声明:我对Typescript / javascript /前端开发仍然是一个新手

背景:我有一组图像(代表一手牌)。当AI轮到玩牌时,我试图显示“思考”的模拟,而不是立即播放卡片。我的模拟是迭代卡片的手并“选择”每一个(通过“选择”,我的意思是将图像稍微向左移动,然后再向右移动。)

我正在使用Visual Studio Code,我正在使用Chrome进行调试。我目前的代码如下。前提是进行API调用(实际上是执行AI逻辑的地方)。然后演示文稿通过卡片的手进行迭代,并且对于每个卡片,它等待1/4秒,将卡片向左移动,等待另外1/4秒,然后将卡片移回右侧。在所有卡被“选中”之后,然后播放实际的卡。我目前拥有回调函数中的所有内容以保持同步,但我不确定我是否需要这样做。

 // Call in to the API, which will perform the AI logic
 // The API will return a slot that was played, which contains the card placed into that slot
 opponentTurn(callback)
 {
   this.boardService.opponentTurn()
       .subscribe(
       cardPlayed =>
       {
         // Set the card played
         let cardData = [];
         cardData = JSON.parse(cardPlayed.toString());

        // To add a slight hint of "thinking", let's "select" (slightly move the card to the left) each card down, up, and back down to the card that the API selected
        this.selectCard(function(_thisagain) {
          // Done
          // Now simulate the move
          _thisagain.dragService.simulateDragDrop(cardData);
        });        

         callback(this);
       }
     );
 }

 // Call this to "select" a card; used by the AI "thinking" simulation
 selectCard(callback)
 {
  for (var i = 0; i < this.players[1].cardHand.length; i++)
  {
    let imgObj = document.getElementById(this.players[1].name + i);     

    if (imgObj != null)
    {
      this.moveCard(imgObj, '400px', function(_thisagain) {
        _thisagain.moveCard(imgObj, '350px', function() {
          // Done
        });
      });
    }
  }

  callback(this);
 }

 moveCard(imgObj, position, callback)
 {
    this.wait(250, function() {
      imgObj.style.right = position;
    });
    callback(this);
 }

 wait(ms, callback)
 {
   var start = new Date().getTime();
   var end = start;
   while(end < start + ms)
    {
      end = new Date().getTime();
    }
    callback(this);
 }

所以我所遇到的困难是代码有效,但只有当我在其上设置断点时。例如,如果我在“_thisagain.moveCard(imgObj,'350px',function(){”行上放置一个断点然后调试它,我可以看到每张卡向左移动并向右移动,如我所料每次我'继续'。如果我删除断点,卡片根本不会移动(但我仍然等待卡片在板上播放之前)。

仍然是Typescript / javascript的新手,我不确定发生了什么。似乎当我设置断点时,会出现重绘以显示卡片移位。没有断点,似乎没有重绘。我不知道如何纠正这个问题,因此我就在这里。

1 个答案:

答案 0 :(得分:0)

因此,经过更多的研究和大量的反复试验,我有了它的工作。真正让我走上正轨的帖子是这样的: DOM refresh on long running function

在那个问题中,有一个答案张贴说: &#34;网页基于单个线程控制器进行更新,一半的浏览器不会更新DOM或样式,直到JS执行停止,将计算控制权交还给浏览器。&#34;

原来那是我失踪的钥匙。我在一个语句中处理得太多了,并且js没有发布回浏览器,因此DOM / html没有被更新以显示&#34;动画&#34;。

然后我使用了jsfiddle的例子,也发布在那里的答案中拼凑了一个&#34;工人&#34;线程将进程分解为基于程序&#34;状态&#34;并使用setTimeout()将控件返回给浏览器。每个工作线程仍然设置为回调函数,以确保每个块中的处理在继续之前完成。出于我原来问题的意图,一切正常。我仍在重构,我确信可能有更好的方法来实现结果,但现在我很满意。

为了帮助将来可能偶然发现我的问题的人,这就是我在工作线程中所拥有的。当然,我选择的术语可能不正确,但其主旨是这一点。当我想开始一个流程时,我可以设置&#34; status&#34;发短信并打电话给工人。然后,工作人员根据需要处理流程。

doHeavyWork() {
    if (this.status == 'finish')
    {
      // All steps done 
    }
    else
    {
      let _this = this;
      switch (_this.status)
      {
        case 'start':
          _this.status = 'working';
          _this.opSelectCard = 0;
          this.opponentTurn(function(response) {
            _this.opCardData = response;
            _this.status = 'selectCard';
          });
          break;

        case 'selectCard':
          _this.status = 'working';
          this.selectCard(_this.opSelectCard, function(response) {
            _this.opImgObj = response;
            _this.status = 'moveCardLeft';
          });
          break;

        case 'moveCardLeft':
          _this.status = 'working';
          this.moveCardLeft(_this.opImgObj, '-25px', function(root) {
            _this.status = 'moveCardRight';
          });
          break;

        case 'moveCardRight':
          _this.status = 'working';
          this.moveCardRight(_this.opImgObj, '1px', function(root) {
            _this.opSelectCard++;
            if (_this.opSelectCard < _this.players[1].cardHand.length)
            {
              _this.status = 'selectCard';
            }
            else
            {
              _this.status = 'simulateDragDrop';
            }
          });
          break;

        case 'simulateDragDrop':
          _this.status = 'working';
          this.dragService.simulateDragDrop(_this.opCardData, function(root) {
            _this.status = 'refreshDisplay';
          });
          break;

        case 'refreshDisplay':
          _this.status = 'working';
          this.refreshCardDisplay(function(root) {
            _this.status = 'refreshDisplay';
          });
          break;

        case 'refreshBoard':
          _this.status = 'working';
          this.refreshBoard(_this.boardCards, function(root) {
            _this.status = 'updateScore';
          });
          break;

        case 'updateScore':
          _this.status = 'working';
          this.updateScore(_this.boardCards, function(_this) {
            _this.status = 'switchTurns';
          });
          break;

        case 'switchTurns':
          _this.status = 'working';
          this.switchTurns(function(_this) {
            if (_this.turn == 1)
            {
              _this.status = 'finish';
            }
            else
            {
              _this.status = 'start';
            }
          });
          break;
      }

      setTimeout(function() {
        _this.doHeavyWork();
      }, 0);
    }
  }