延迟和承诺循环

时间:2015-06-22 19:27:48

标签: javascript jquery for-loop promise jquery-deferred

我试图在循环的上下文中使用deferred和promises,但我没有这样做。

我需要异步调用第一个方法。第一种方法(让我们称之为getArray())返回一个数组。

对于数组的每个元素,我需要调用第二个方法,让我们称之为getData(id)。 id存储在getArray返回的数组中。

最后,一旦我得到getData()的结果,我需要使用结果来调用第三个方法,让我们称之为getDetails()。

完成所有调用并完成循环后,我需要返回数组,并提供额外的数据和详细信息。

我创建了一个jsfiddle: http://jsfiddle.net/chevdor/953sLkts/

var myarray = [];

var log = function(s){
    $('#console').append('<p>'+s+'</p>');
};

var get1 = function() {
    var dfd = jQuery.Deferred();
    log('Running get1');
    setTimeout(function() { 
        var res = [1, 2, 3, 4];

        // that´s probably crap...
        for (var i= 0; i< res.length; i++){
            get2(res[i])
                .done(get3(res[i])
                    .done(get4(res[i]))
            );
        }

        dfd.resolve(res);
    }, Math.floor(400 + Math.random() * 1000));
    return dfd.promise();
};

var get2 = function(index) {
    var dfd = jQuery.Deferred();
    log('Running get2');

    setTimeout(function() { 
        var res = {
            index: index,
            val: index * 2
        };
        myarray[index]= res;
        dfd.resolve(res);
    }, Math.floor(400 + Math.random() * 1000));
    return dfd.promise();
};

var get3 = function(index) {
    var dfd = jQuery.Deferred();
    log('Running get3');

    setTimeout(function() { 
        var res = {
            index: index,
            val2: index * index
        };
        myarray[index].extra =  res;

        dfd.resolve(res);
    }, Math.floor(400 + Math.random() * 1000));
    return dfd.promise();
};

var get4 = function(index) {
    var dfd = jQuery.Deferred();
    log('Running get4');

    setTimeout(function() { // Resolve after a random interval
        var res = {
            index: index,
            val2: index * index
        };
        dfd.resolve(res);
    }, Math.floor(400 + Math.random() * 1000));
    return dfd.promise();
};

log('start');
get1();

来说明。它肯定不起作用,看起来很难看......

你能解释一下这样做的正确方法吗?

2 个答案:

答案 0 :(得分:1)

我可以向您介绍$ .when。

从你的代码看,你的get2(),get3(),get4()看起来像是getData(),getDetail()。假设他们都像承诺一样。然后你可以这样做:

import wx
import socket
import threading
import sys

class oranges(wx.Frame):
    def __init__(self,parent,id):

        ##Unimportant stuff
        wx.Frame.__init__(self,parent,id," Retro Message",size=(500,500))
        self.frame=wx.Panel(self)
        self.input_box=wx.TextCtrl(self.frame, -1,pos=(15,350),size=(455,120),style=wx.NO_BORDER| wx.TE_MULTILINE)
        self.messaging_box=wx.TextCtrl(self.frame, -1,pos=(15,15),size=(455,285),style=wx.NO_BORDER | wx.TE_MULTILINE|wx.TE_READONLY)
        send_button=wx.Button(self.frame,label="Send",pos=(350,315),size=(75,40))
        self.Bind(wx.EVT_BUTTON, self.sender,send_button)
        self.Bind(wx.EVT_CLOSE, self.close_window)
        self.counter = 1
        self.socket_connect = socket.socket()
        self.setup()

    def sender(self,event):
        self.socket_connect.send(self.input_box.GetValue())
        self.input_box.Clear()
        self.Refresh()

        ##Important stuff
    def close_window(self,event): #This is the function in question#
        self.counter = 0
        self.socket_connect.shutdown(socket.SHUT_RDWR)
        sys.exit(0)
    def setup(self):
        self.ip_enter = wx.TextEntryDialog(None, "Enter in the IP:", "Setup", "192.168.1.1")
        if self.ip_enter.ShowModal() ==wx.ID_OK:
            self.offical_ip = self.ip_enter.GetValue()
            try:
                self.socket_connect.connect((self.offical_ip,5003))
                self.username = "false" #Tells the server just to give the user a IP username
                self.Thread1 = threading.Thread(target = self.listening_connect)
                self.Thread1.start()
            except socket.error:
                self.error_connect()
        else:
            sys.exit(0)

    def listening_connect(self):
        self.socket_connect.send(self.username)
        while self.counter != 0:
            data = self.socket_connect.recv(1024)
            self.messaging_box.AppendText(data)
            self.Refresh()
            if not data:
                break
        self.socket_connect.close()         
    def error_connect(self):
        pop_ups = wx.MessageDialog(None, "Failed to Connect to Server!", 'Error', wx.OK)
        pop_ups.ShowModal()
        self.setup()

if __name__=="__main__":
    app=wx.App(False)
    window=oranges(parent=None,id=-1)
    window.Show()
    app.MainLoop()

我是蓝鸟承诺的忠实粉丝,关键字是.all()而不是.when()。我不确定jquery承诺如何工作,但我相信它是一个非常相似的结构。希望这可以帮助。如果不清楚,请告诉我:)。

编辑:很抱歉混淆,在promises数组上使用$ .when,语法为:

import socket

HOST = '192.168.1.1'
PORT=5003
s = socket.socket()
s.bind((HOST, PORT))
s.listen(1)
c,addr = s.accept()
while True:
    data = c.recv(1024)
    if not data:
        break
c.close()

注意这里的“数据”只是从promise1解析的,我不熟悉jquery。但我确实建议bluebird承诺。哪个更快更干净。

答案 1 :(得分:0)

尝试创建p.push()到[{1}}的结果数组$.when(get2(res[i]), get3(res[i]), get4(res[i]))p;通过$.when.apply调用p作为传递的jQuery承诺对象的数组;检查dfd.resolve(res)的{​​{1}},myarray .then onFulfilled处理程序的结果get1

var myarray = [];

var log = function(s){
    $('#console').append('<p>'+s+'</p>');
};

var get1 = function() {
    var dfd = jQuery.Deferred();
    log('Running get1');
    var p = [];
    setTimeout(function() { 
        var res = [1, 2, 3, 4];

        // that´s probably crap...
		for (var i= 0; i< res.length; i++){
			p.push($.when(get2(res[i]), get3(res[i])
            , get4(res[i])))
            
		};
        
        $.when.apply($, p).then(function() {
          dfd.resolve($.makeArray(arguments))
        })
        
        
    }, Math.floor(400 + Math.random() * 1000));
    return dfd.promise();
};

var get2 = function(index) {
    var dfd = jQuery.Deferred();
    log('Running get2');

    setTimeout(function() { 
        var res = {
            index: index,
            val: index * 2
        };
        myarray[index]= res;
        dfd.resolve(res);
    }, Math.floor(400 + Math.random() * 1000));
    return dfd.promise();
};

var get3 = function(index) {
    var dfd = jQuery.Deferred();
    log('Running get3');

    setTimeout(function() { 
        var res = {
            index: index,
            val2: index * index
        };
        myarray[index] = {"extra":res};
        
        dfd.resolve(res);
    }, Math.floor(400 + Math.random() * 1000));
    return dfd.promise();
};

var get4 = function(index) {
    var dfd = jQuery.Deferred();
    log('Running get4');

    setTimeout(function() { // Resolve after a random interval
        var res = {
            index: index,
            val2: index * index
        };
        dfd.resolve(res);
    }, Math.floor(400 + Math.random() * 1000));
    return dfd.promise();
};

log('start');
get1().then(function() {
  console.log("res:", arguments, "myarray:", myarray);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<h1>Test</h1>
<span id='console'></span>

jsfiddle http://jsfiddle.net/953sLkts/9/