2014-12-22 2 views
0

я получил класс машинопись с атрибутом, который содержит некоторые данные соединения, которые являются результатом вызова Ajax, вот фрагмент кода:Машинопись Последовательность методов класса

class User { 
    // ... other stuff (constructor, attributes, methods) 
    static data:{id:number; token:string} = {id: 0, token: ""}; 
    connect() { 
     // Ajax Call 
     .done(function(e){ 
      User.data.id = e.id; 
      User.data.token = e.token; 
     }) 
    } 
    request() { 
     if(User.data.id == 0) 
      setTimeout(() => { 
       this.request(); 
      }, 500); 
     else return '?id=' + User.data.id + '&token=' + User.data.token; 
    } 
} 

Я пытался использовать connect() и впоследствии request() но иногда функция request() запускается перед ответом ajax. Теперь я пытаюсь написать функцию request() с некоторым временем ожидания и своего рода рекурсией. К сожалению, это не работает. Моя цель - вызвать функцию request() и получить строку только тогда, когда готовы «id» и «токен» (а не 0 и пустая строка). Любое предложение будет оценено!

PS: Я не могу поставить функцию request() внутри AJAX обратного вызова: две функции должны быть разделены

ответ

0

Вызывающий код должен сочетать обещания с then. connect() и request() должны просто вернуть свои обещания. например они «обещают вернуться к работе при подключении» и «обещают вернуть запрошенные данные». В случае request, он не нуждается в объекте или обещании deferred, так как он просто сразу возвращает значение.

JSFiddle пример: http://jsfiddle.net/TrueBlueAussie/qcjrLv4k/3/

// Return a fake connection after 5 seconds 
var connect = function(){ 
    var def = $.Deferred(); 
    setTimeout(function(){ 
     def.resolve(); 
    }, 5000); 
    return def.promise(); 
} 

var request = function(){ 
    return "?data=d"; 
} 

и использовать так:

connect().then(request).done(function(data){ 
    alert(data); 
}); 

Так что в вашем случае просто возвращает результат Ajax вызова как обещание от connect():

connect() { 
     return $.ajax({[snipped]}) 
     .done(function(e){ 
      User.data.id = e.id; 
      User.data.token = e.token; 
     }); 
    } 

и request просто возвращает строку:

request() { 
    return '?id=' + User.data.id + '&token=' + User.data.token; 
} 

Другой способ сделать это, чтобы спасти connect обещание:

var promise = connect(); 

и использовать его всякий раз, когда вы хотите получить данные request:

promise.then(request).done(function(data){ 
    alert(data); 
}); 

Лучший способ , если ваш request зависит от «соединения», должен передать обещание connect на номерметод в качестве требуемого параметра:

request(connectionPromise){ 
    return connectionPromise.then(function(){ 
     return '?id=' + User.data.id + '&token=' + User.data.token; 
    }); 
}; 

и колл с:

request(connect()).done(function(data){ 
    alert(data); 
}); 

примера с использованием этого подхода здесь: http://jsfiddle.net/TrueBlueAussie/qcjrLv4k/4/

Заключительный пример (на основе комментировал желание повторно использовать соединение). Объедините предыдущие ответы следующим образом:

1) Сохраните соединение как свойство объекта.

// Start the connection process and save the promise for re-use 
var connectionPromise = connect(); 

2) Используйте соединение в качестве параметра на запросы (так что они не должны иметь знания о внешней переменной):

// Make a request, passing the connection promise 
request(connectionPromise).done(function(data){ 
    alert(data); 
}); 

3) Метод запроса не изменяется от предыдущий пример:

request(connectionPromise){ 
    return connectionPromise.then(function(){ 
     return '?id=' + User.data.id + '&token=' + User.data.token; 
    }); 
}; 
+0

Tnx для вашего ответа, я буду углубленно изучать эти аргументы. В вашем коде каждый запрос попытается дождаться, пока соединение будет разрешено, но это не хорошо для меня, потому что в моем коде мне нужна возможность сделать несколько «request()» только с одним начальным соединением, и проблема только с первый запрос (иногда данные подключения к нему не готовы). – Plastic

+0

@Plastic: я добавлю дополнительные опции, в частности, исходя из вашего желания повторно использовать соединение. –

+0

Огромное вам спасибо, моя первая цель - узнать что-то полезное;) – Plastic

0

После того, как вы в обещание земли вы должны остаться там (или использовать функцию обратного вызова):

class User { 
    // ... other stuff (constructor, attributes, methods) 
    static data: { id: number; token: string } = { id: 0, token: "" }; 

    private connectedPromise; 
    connect() { 
     // Ajax Call 
     this.connectedPromise = something.done(function (e) { 
      User.data.id = e.id; 
      User.data.token = e.token; 
     }) 
    } 
    request() { 
     this.connectedPromise.then(() => { 
      if (User.data.id == 0) 
       setTimeout(() => { 
        this.request(); 
       }, 500); 
      else return '?id=' + User.data.id + '&token=' + User.data.token; 
     }) 
    } 
} 

Сохраните результат подключения в var, чтобы выполнить только запрос выполнения, если соединение разрешено.

PS функция запроса плохо (я не почистили, но убрали возвращение) в том, что это может быть, асинхронной, т.е. она либо возвращает значение, или делает некоторые асинхронной работы. Лучше быть последовательным и всегда быть асинхронным.

+0

Вы сказали, что мне нужно остаться с обещанием или использовать обратный вызов .. Ведьма лучше? – Plastic

+1

Определенно обещает – basarat

+0

@basarat: обещания должны быть закованы в цепочку, не сшиваться вместе, добавляя зависимости (в вашем случае переменная 'connectedPromise'). Добавьте пример. –

Смежные вопросы