Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 带承诺的异步循环?_Javascript_Typescript_Ecmascript 6_Promise_Es6 Promise - Fatal编程技术网

Javascript 带承诺的异步循环?

Javascript 带承诺的异步循环?,javascript,typescript,ecmascript-6,promise,es6-promise,Javascript,Typescript,Ecmascript 6,Promise,Es6 Promise,下面的代码注册了一系列socketio名称空间。部分逻辑依赖于通过sequelize进行的数据库调用,因此我需要使用Promissions。我希望当所有名为logic的构造函数都完成时,完整的承诺得到解决。但我的问题是,在emitInitialPackage函数解决之前,完整的承诺就解决了 export class demoClass { public complete: Promise<boolean>; server: any; constructor(

下面的代码注册了一系列socketio名称空间。部分逻辑依赖于通过sequelize进行的数据库调用,因此我需要使用Promissions。我希望当所有名为logic的构造函数都完成时,完整的承诺得到解决。但我的问题是,在emitInitialPackage函数解决之前,完整的承诺就解决了

export class demoClass {
    public complete: Promise<boolean>;
    server: any;

    constructor(io: any) {
        this.server = io;
        this.complete = Promise.resolve(db.Line.findAll()).then(lines => {
                // do some mapping to generate routes and cells
                this.registerEndPoints(routes, [], cells);
            }).catch(err => console.log(err))
    }



registerEndPoints(routes: Array<string>, nsps: Array<any>, cells: Array<string>) {
        for (let i = 0; i < routes.length; i++) {
            nsps.push(this.server.of('/api/testNamespace/' + routes[i]));
            let that = this;
            const nsp = nsps[i];
            nsp.on('connection', function (socket) {
                that.emitInitialPackage(nsps[i], routes[i], cells[i]);
            });
        }
    }

    emitInitialPackage(nsp: any, name: string, cell: any) {
        return db.Line.find({/* Some sequelize params*/}).then(results => {
            nsp.emit('value', results);
        }).catch(err => console.log(err));
    }
}

如何确保emitInitialPackage在完成解析之前已完成?

若要等待registerEndPoints中所有操作的完成,此方法应返回可在db.Line.findAll操作后链接的承诺:

export class demoClass {
    public complete: Promise<boolean>;
    server: any;

    constructor(io: any) {
        this.server = io;
        this.complete = Promise.resolve(db.Line.findAll()).then(lines => {
            // return promise created by registerEndPoints method
            return this.registerEndPoints(routes, [], cells);
        }).catch(err => console.log(err))
    }   

    registerEndPoints(routes: Array<string>, nsps: Array<any>, cells: Array<string>) {
        const endPointPromises = routes.map((route, index) => {
          // for each endpoint create Promise that gets resolved 
          // only when all work for endpoint is done
          return new Promise((resolve) => {
              nsps.push(this.server.of('/api/testNamespace/' + route));
              const nsp = nsps[index];
              nsp.on('connection', (socket) => {
                // resolve promise when emitInitialPackage did its part of the work
                this.emitInitialPackage(nsps[index], route, cells[index]).then(resolve);
              });          
          });
        });

        return Promise.all(endPointPromises);
    }

    emitInitialPackage(nsp: any, name: string, cell: any) {
        return db.Line.find({/* Some sequelize params*/}).then(results => {
            nsp.emit('value', results);
        }).catch(err => console.log(err));
    }
}

有几个问题需要解决:

返回this.registerEndPoints返回的承诺,因此this.complete仅在该承诺解决时才会解决; 为nsps参数传递的[]参数没有作为参数的作用,因此您最好将该参数一起跳过; 关于“连接”的。。。函数应该被包装以返回一个承诺; for循环应该创建这些承诺,然后将它们传递给Promise.all以获得最终结果。地图可用于此; 如果有三个数组、路由、单元和NSP,它们在相同的索引处具有相关数据,那么这种结构就不好。更好的结构是有一个对象数组,每个对象有三个属性:路由、单元和nsp; bluebird是promises/A+兼容的,因此不需要将bluebird promise转换为原生JS promise。 以下是一些未经测试的代码:

constructor(io: any) {
    this.server = io;
    // *** bluebird is promises/A+ compliant, no need to convert it:
    this.complete = db.Line.findAll().then(lines => {
        // do some mapping to generate routes and cells
        // *** return the promise!
        // *** removed [] argument: not needed
        return this.registerEndPoints(routes, cells);
    }).catch(err => console.log(err))
}

// *** Remove the nsps parameter
registerEndPoints(routes: Array<string>, cells: Array<string>) {
    // *** Create a promise-version of the `.on('connection', ...)` method
    function nspConnect(nsp) {
        return new Promise( resolve => nsp.on('connection', resolve) );
    }
    let that = this;
    // *** Combine each route, cell, and nsp in one object, and put in array:
    const data = routes.map( (route, i) => ({
        nsp: that.server.of('/api/testNamespace/' + route),
        route,
        cell: cells[i]
    }) );
    // *** Map the array of objects to promises
    const proms = data.map( ({nsp, route, cell}) =>
        nspConnect(nsp).then(that.emitInitialPackage.bind(that, nsp, route, cell)) );
    // *** Return a promise that resolves when all these have resolved
    return Promise.all(proms); 
}

不能将循环与异步代码一起使用。。。需要循环asynchronously@elclanrs好的,那么异步循环是什么样子的呢?这里有点不太清楚?this.server.of做什么/返回什么?构造函数中的单元格来自何处,registerEndPoints中的nsp是什么?为什么要等待nsp连接,然后关闭返回的套接字?为什么要这样做:Promise.resolvedb.Line.findAll?findAll重新运行一个承诺,或者它是同步的,或者它需要一个回调函数。在所有这些情况下,将其包装在承诺中都不会有任何好处。@Thomas this.server.of返回一个socketio命名空间。如上面注释的行中所述,单元格和路由是从行映射的。我将更新代码示例以更正此问题,但nsp是nsps的成员。不确定等待nsp连接是什么意思?findAll返回一个bluebird承诺,因此我使用promise.resolve将其转换为es6承诺您需要更新registerEndPoints以返回一个承诺,该承诺在所有emitInitialPackage调用完成时完成。然后将该承诺作为完整通话的一部分返回。这允许承诺流动或真正映射通过感谢你!您能解释一下nspConnect中的行吗nspConnect什么是resolve?nspConnect是一个返回承诺的函数。该承诺在调用对nsp.on的回调时解析。Promise构造函数总是将两个函数作为参数传递给提供给它的回调:resolve和reject。它们是承诺内部人员给出的句柄,用于解决承诺或拒绝承诺。我忽略了第二个。我提供resolve函数作为对nsp.on的回调,以便在建立连接时调用此解析。调用此resolve函数时,它将解析新承诺。但为什么要将resolve作为nsp.on的参数传入?因为on函数在完成它的任务时将调用第二个参数回调,当它执行时,我希望执行resolve,因为现在是解析承诺的时候了,所以这就是我将它传递给on的原因。好的,这个解决方案将使用什么包?
function nspConnect(nsp) {
    return new Promise( resolve => { 
        console.log('creating promise'); 
        return nsp.on('connection', socket => { 
            console.log('resolving'); 
            resolve();
        }); 
    });
}