function shiftini(emo,dest){
start=emo.offsetLeft;
pot=start;
step=(dest-start)/10;
end=dest;
if(start>dest) lr=1; else lr=-1;
ele=emo;
shiftact();
}
function shiftact(){
if((end-pot)*lr<0){
        pot+=step;
ele.style.left=pot+"px";
setTimeout("shiftact()",40);
}
}这是我自定义的一段动态移动控件的递归程序, 实现平滑左右移动的效果,通过页面的按钮运行shiftini.
现在的问题是移动过程中, 如果再连续按移动位置会不准确, 想控制其在移动过程完成后才能再执行下一个shiftini.
因为使用了setTimeout, 所以涉及到了异步的问题, 这里要怎么回调呢?
如果使用promises 怎么做, 看了些资料对这个真理解不上去, 不知道怎么具体的应用, 谁能根据我这个给个例子.

解决方案 »

  1.   

    外面设置一个状态 变量var status;function shiftini(){
           switch(status){
                 case '移动中' :return;
                 case '停止中':
                      status=‘移动中’
                      ......代码
                 break;
          }
    }
    function shiftact(){
        if(....){
               ......
        }else{
              status = '等待中'
        }
      

  2.   

    设置一个manager,类似数组的东西
    点击的时候将动作存进去,直到一个动作完成,再去manager里面获取一下执行,删除上一个
    这样好处是可以自行判断剩下的动作是否应该继续执行下去,可以自己取消动作
    就是可控制性强一点.
      

  3.   

    方法简单, 的确可以解决我的问题, 多谢.
    另外, 如果想获得上一次移动后的距离怎么处理, 比如 ele.style.left 得到上一次移动的位置, 如果移动的距离很长, 有一定延迟, 无法获得,要怎么解决.
      

  4.   

    xxo1986cxm 你说这个有点像promises管道的意思, 这个数组里存储的应该是哪部分呢? 是我的shiftini这部分,还是递归部分? 另外如果这么做是不是就不需要使用递归了?
      

  5.   

    定义一个全局变量InitialX表示控件移动前初始位置
    var InitialX=ele.offsetLeft;当停止移动的时候,计算移动距离:
    var distance=ele.offsetLeft-InitialX;
    然后把新位置赋值给InitialX
    InitialX=ele.offsetLeft
      

  6.   

    差不多有点队列先进先出的意思吧
    存储什么看你自己的写法了,只要能确定执行的东西就可以
    递归的话,应该是没必要,前提是你能确保shiftini执行结束的时候才调用到下一个动作或者判断是否满足条件结束动作并清除队列数据总之是先进先出,执行完一个就Next,只要满足你的条件,就把队列里面剩下的动作清空,当然也可以不清空
      

  7.   

    如果用这种方式,这么重写, 思路对不:
    1 取消setTimeout将shiftact()逐个加入队列, 然后没两个中间夹一个延迟40ms函数.
    2 使用循环判断条件, 逐个执行队列中函数.
    3 shiftini() 也加入另一个队列, 每点击一次按钮, 加入一个, 然后逐个执行.
    4 shiftact队列中, 每次函数执行后返回一个值, 将这个值作为参数给下一个shiftact. shiftini 同理.
    第4步的返回值也要建个全局变量传参, 感觉好复杂.