2013-07-23 33 views
5

Tôi có trang web này kết nối với một dịch vụ địa phương quản lý một CardReader với một PIN Pad. Có nhiều thao tác khác nhau có thể được hoàn thành bằng thiết bị này. Heres một ví dụ về một trong số họ:Cách quản lý các cuộc gọi AJAX bị xích với jQuery

  1. Khóa điện thoại
  2. Hỏi mã PIN số
  3. thiết bị phát hành

Trước khi tôi sử dụng để chuỗi các callbacks giữa mỗi khác, nhưng bây giờ, bởi vì có các hoạt động mới, cũng sử dụng các phương pháp như "khóa" và "giải phóng", tôi cần thay đổi mã của mình, để mã cho bước 1 và 3 có thể sử dụng lại được.

Tôi đã cố gắng giải quyết vấn đề này với lời hứa của jQuery, nhưng Im khá mới mẻ với điều này, và tôi vẫn chưa thực sự tìm ra cách chúng hoạt động. Ai đó có thể cho tôi một tay không?

Đây là ví dụ về mã đang sử dụng ngay bây giờ. Tôi đã xóa logic nghiệp vụ khỏi bên trong các chức năng, để đơn giản hóa ví dụ:

var CardReader = { 

    //////////////////// 
    // Different possible messages to the Card Reader 
    //////////////////// 

    lockDevice: function() { 
     this.makeAjaxCall("GET", "/LockDevice", this.lockDeviceCallback); 
    }, 

    getPin: function() { 
     this.makeAjaxCall("POST", "/getPin", this.getPinCallback); 
    }, 

    releaseDevice: function() { 
     this.makeAjaxCall("POST", "/Release", this.releaseDeviceCallback); 
    }, 

    ////////////////// 
    // Callbacks for each message to the Card Reader 
    ////////////////// 

    lockDeviceCallback: function(jqXHR, textStatus) { 
     if (textStatus !== "success") { return; } 
     this.getCardLogin(); 
    }, 

    getCardLoginCallback: function(jqXHR, textStatus) { 
     if (textStatus !== "success") { return; } 
     this.releaseDevice(); 
    }, 

    releaseDeviceCallback: function(jqXHR, textStatus) { 
     if (textStatus !== "success") { return; } 
     //End 
    }, 

    //////////////// 
    // Other methods 
    //////////////// 

    init: function() { 
     // UI BIndings 
     $(#button).on("click", this.logIn.bind(this)); 
    }, 

    logIn: function() { 
     this.lockDevice(); 
    }, 

    makeAjaxCall: function(callType, resource, callbackMethod) { 

     $.ajax({ 
      type  : callType, 
      url  : "http://localhost:1337" + resource, 
      cache  : false, 
      dataType : "json", 
      contentType: "application/json", 
      context : this, 
      complete : callbackMethod 
     }); 
    } 
}; 

Trả lời

1

Điều này có thể phù hợp với nhu cầu của bạn ngay cả khi tôi không chắc chắn hiểu đầy đủ vấn đề của bạn ở đây.

Điểm quan trọng ở đây dường như giữ trật tự trên phương thức callback ajax. Bạn có thể làm một cái gì đó như thế:

Tạo những phương pháp:

_nextCall: function (deferreds, method) { 
     if (deferreds.length) this._when(deferreds, method); 
     else console.log(method + " SUCCESS"); 
    }, 
    _when: function (calls, method) { 
     var $promise = $.when(this[calls[0]]()) 
     $promise.then(function() { 
      calls.splice(0, 1); 
      this._nextCall(calls, method); 
     }, function() { 
      console.log(method + " FAILED on: " + calls[0]); 
     }); 
    }, 

Sử dụng nó như ví dụ rằng:

logIn: function logIn() { 
     var calls = ["lockDevice", "getCardLogin", "releaseDevice"]; 
     this._when(calls, arguments.callee.name); 
    }, 
    getPinOnly: function getPinOnly() { 
     var calls = ["getPin"]; 
     this._when(calls, arguments.callee.name); 
    }, 

DEMO

COMPLETE Mã sản phẩm:

var CardReader = { 

    //////////////////// 
    // Different possible messages to the Card Reader 
    //////////////////// 

    lockDevice: function() { 
     return this.makeAjaxCall("GET", "/LockDevice", this.lockDeviceCallback); 
    }, 
    getCardLogin: function() { 
     return this.makeAjaxCall("POST", "/getCardLogin", this.getCardLoginCallback); 
    }, 
    getPin: function() { 
     return this.makeAjaxCall("POST", "/getPin", this.getPinCallback); 
    }, 

    releaseDevice: function() { 
     return this.makeAjaxCall("POST", "/Release", this.releaseDeviceCallback); 
    }, 

    ////////////////// 
    // Callbacks for each message to the Card Reader 
    ////////////////// 

    lockDeviceCallback: function (jqXHR, textStatus) { 
     console.log("lockDeviceCallback"); 
     if (textStatus !== "success") { 
      return; 
     } 
    }, 

    getCardLoginCallback: function (jqXHR, textStatus) { 
     console.log("getCardLoginCallback"); 
     if (textStatus !== "success") { 
      return; 
     } 
    }, 
    getPinCallback: function (jqXHR, textStatus) { 
     console.log("getPinCallback"); 
     if (textStatus !== "success") { 
      return; 
     } 
    }, 

    releaseDeviceCallback: function (jqXHR, textStatus) { 
     console.log("releaseDeviceCallback"); 
     if (textStatus !== "success") { 
      return; 
     } 
     //End 
    }, 

    //////////////// 
    // Other methods 
    //////////////// 

    init: function() { 
     // UI BIndings 
     $('#btn_login').on("click", $.proxy(this.logIn, this)); 
     $('#btn_getPinCallback').on("click", $.proxy(this.getPinOnly, this)); 
    }, 
    _nextCall: function (deferreds, method) { 
     if (deferreds.length) this._when(deferreds, method); 
     else console.log(method + " SUCCESS"); 
    }, 
    _when: function (calls, method) { 
     var $promise = $.when(this[calls[0]]()) 
     $promise.then(function() { 
      calls.splice(0, 1); 
      this._nextCall(calls, method); 
     }, function() { 
      console.log(method + " FAILED on: " + calls[0]); 
     }); 
    }, 
    logIn: function logIn() { 
     var calls = ["lockDevice", "getCardLogin", "releaseDevice"]; 
     this._when(calls, arguments.callee.name); 
    }, 
    getPinOnly: function getPinOnly() { 
     var calls = ["getPin"]; 
     this._when(calls, arguments.callee.name); 
    }, 

    makeAjaxCall: function (callType, resource, callbackMethod) { 

     return $.ajax({ 
      type: callType, 
      url: "/echo/json", // + resource, 
      cache: false, 
      dataType: "json", 
      contentType: "application/json", 
      context: this, 
      success: callbackMethod 
     }); 
    } 
}; 

CardReader.init(); 
1

Sử dụng thư viện hứa hẹn đầy đủ tính năng hơn. Hãy xem: https://github.com/kriskowal/q Bạn nên dành chút thời gian để hiểu vì nó cải thiện đáng kể phong cách và khả năng đọc mã của bạn. Về cơ bản bạn có thể viết mỗi chức năng kinh doanh để nó trả về một lời hứa, vì vậy giống như sau: -

function myBusinessFunction(params) { 
    var deferred = Q.defer(); 
    .... 
    doSomeAsyncFunction(params,function(error,result) { 
     if (error) { 
      deferred.reject(new Error(error)); //pass the error on 
     } else { 
      deferred.resolve(result); 
     } 
    }); 
    return deferred.promise; 
} 

Vì vậy, những gì đang xảy ra ở đây là cho mỗi hoạt động async mà bạn làm tạo một hàm, bên trong đó tạo ra một trì hoãn và trả lại. Ngay sau khi bạn nhận được một thời gian chờ hoặc một lỗi hoặc bất kỳ kết quả sau đó bạn gọi deferred.reject hoặc deferred.resolve.

Với sự bổ sung đó để mã của bạn sau đó bạn có thể tránh địa ngục gọi lại nơi bạn có rất nhiều chức năng lồng nhau và tạo tổng thể một cái gì đó đang thuật toán của bạn như sau: -

Q.fcall(promisedStep1) 
.then(promisedStep2) 
.then(promisedStep3) 
.then(promisedStep4) 
.then(function (value4) { 
    // Do something with value4 
}) 
.catch(function (error) { 
    // Handle any error from all above steps 
}) 
.done(); 

này gần giống với lần thử ... bắt lập trình theo phong cách thủ tục rất quen thuộc nhưng bạn thực sự đang xử lý các quy trình không đồng bộ. Khi bạn gọi từ chối trên lời hứa thì luồng điều khiển sẽ chuyển tới hàm catch rất đơn giản hóa việc lập trình.

Có nhiều chức năng và tính năng bổ sung trong thư viện để bạn có thể đối phó với các bước chạy song song, v.v.Kiểm tra các tài liệu nó cũng có giá trị nó.

1

Hãy thử async: false với cuộc gọi Ajax của bạn. Điều này đầu tiên hoàn thành bạn gọi Ajax, và sau đó thực hiện các câu lệnh khác.

makeAjaxCall: function (CALLTYPE, tài nguyên, callbackMethod) {

$.ajax({ 
     type  : callType, 
     url  : "http://localhost:1337" + resource, 
     cache  : false, 
     dataType : "json", 
     contentType: "application/json", 
     context : this, 
     async :false, 
     complete : callbackMethod 
    }); 
} 
-1
 jQuery.support.cors = true; 

     $.ajax({ 
      type: "POST", 
      contentType: "application/json; charset=utf-8", 
      datatype: "json",    
      async :false, 
      url: "http://yourHost:portnumeber/ServiceName/LockDevice", 
      success: 
     lockDeviceCallback, 
      error: 
     function (XmlHttpRequest, textStatus, errorThrown) { 
      errorHandler(XMLHttpRequest); 
     } 
     });    
Các vấn đề liên quan