Javascript 添加了异步行为,无法使代码适合它

Javascript 添加了异步行为,无法使代码适合它,javascript,jquery,ajax,Javascript,Jquery,Ajax,以前我用过 //get state MyClass.prototype.getState = function(key) { var value; switch(this._options.type){ case "cookie": value = $.cookie(key); break; case "localStorage":

以前我用过

//get state
   MyClass.prototype.getState = function(key) {
       var value;
       switch(this._options.type){
          case "cookie":
                value = $.cookie(key);
                break;

          case "localStorage":
                value = window.localStorage.getItem(key);
                break;
        }

        this._options.afterGetState(key, value);
        return value;
    };

   //set state
   MyClass.prototype.setState = function(key, value) {
        switch(this._options.type){
          case "cookie":
                $.cookie(key, value); 
                break;

          case "localStorage":
                window.localStorage.setItem(key, value));
                break;
        }
        return this._options.afterSetState(key, value);
      };



    MyClass.prototype.ended = function() {
        return !!this.getState("is_ended");
      };

    MyClass.prototype.setStep = function(value) {
        if (value != null) {
          this._current = value;
          return this.setState("step", value);
        } else {
          this._current = this.getState("step");
          if (this._current === null || this._current === "null") {
            return this._current = 0;
          } else {
            return this._current = parseInt(this._current);
          }
        }
      };

      MyClass.prototype.end = function() {
        this.setState("end", "true");
      };
已经使用了本地存储和cookie。现在我添加了在db中存储数据的功能,因此我必须使用ajax和异步函数。所以我改变了密码:

//get state async
   MyClass.prototype.getState = function(key, callback) {
        oldThis = this;
        //h-mmm... what if callback is null or undefined? Will it work for function(){ }?
        callback = typeof callback != 'undefined' ? callback : function(){ }
        switch(this._options.storageType){

          case "cookie":
            setTimeout(function(){ 
                    value = callback($.cookie(key)); 
                    oldThis._options.afterGetState(key, value);
                    return value;
                  },
              0);
            break;

          case "localStorage":
            setTimeout(function(){ 
                  callback(window.localStorage.getItem(key));
                  oldThis._options.afterGetState(key, value);
                  return value;
                },
              0);
            break;

          case "db":
            $.ajax({
                type: "GET",
                url: "/123",
                data: { .... },
                success: function(data){
                  value = callback(data);
                  oldThis._options.afterGetState(key, value);
                  return value;
                },
                error: function() {
                  alert('Error occured');
                  return undefined;
                }
            });
            break;
        }
      };

  //set state async
  MyClass.prototype.setState = function(key, value, callback) {
        oldThis = this;
        callback  = callback || function(){ }
        switch(this._options.storageType){
          case "cookie":
                setTimeout(function(){ 
                        callback($.cookie(key, value)); 
                        return oldThis._options.afterSetState(key, value);
                     },
                0);
                break;

          case "localStorage":
                setTimeout(function(){ 
                      callback(window.localStorage.setItem(key, value));
                      return oldThis._options.afterSetState(key, value);
                    },
                0);
                break;

          case "database":
                $.ajax({
                    type: "POST",
                    url: "123",
                    data: { .... },
                    success: function(data){
                      callback(data);
                      return oldThis._options.afterSetState(key, value);
                    },
                    error: function() {
                        alert('Error occured');
                    }
                });
            break;
        }
      };
那么如何更改prototype.end、prototype.setStep和prototype.end函数呢?以下是我所做的:

//nothing has been changed. Is this correct? It seems to be so.
MyClass.prototype.ended = function() {
    return !!this.getState("end");
  };

MyClass.prototype.setStep = function(value) {
    if (value != null) {
      this._current = value;
      return this.setState("step", value, function(value){ return value; });
    } else {
        oldThis = this;
        this.getState("step", function(value){ oldThis._current = value; });
      if (this._current === null || this._current === "null") {
        return this._current = 0;
      } else {
        return this._current = parseInt(this._current);
      }
    }
  };

//nothing has been changed. Is this correct as well?
  MyClass.prototype.end = function() {
    this.setState("end", "true");
  };

底线是,我不知道应该从哪里返回值:从
prototype.setState和prototype.getState
或从
prototype.end、prototype.enden和prototype.setStep

处理异步操作时,必须使用回调函数而不是
return
语句

例如,此同步代码:

function syncFunc() {
    return 10;
}
var val = syncFunc();
doSomethingWithVal(val);
当函数是异步的时,应该变成这样:

function asyncFunc(callback) {
    setTimeout(function() {
       var data = 10;
       // Call the callback when async op is finished
       callback(data);
    }, 1000);
}
asyncFunc(doSomethingWithVal);

就您的特定代码而言,这意味着这将不起作用:

MyClass.prototype.ended = function() {
    return !!this.getState("end");
};

您无法从
end
返回(它可能总是返回
undefined
,因为
getState
将在回调之前返回)。你不能再使用像
var x=obj.end()
这样的东西了,你必须重新考虑你的逻辑。对于
setStep
,情况也是如此,您不能只返回
getState
的返回值,因为它现在是异步的。

doSomethingWithVal看起来像什么?可以是empy-like function(){}?可以,但在这种情况下,您甚至不需要回调。。。我的示例试图说明不能使用异步函数的返回值,必须在异步操作完成时向它们传递另一个要调用的函数。
setTimeout
也只是一个模拟异步操作(如数据库访问)的示例。doSomethingWithVal或callback必须返回任何值吗?不,其目的就是不要使用
return
语句。@AlanDert我添加了一些关于代码的特定注释,希望对您有所帮助。