返回时能否兑现承诺?

时间:2019-06-08 02:29:26

标签: javascript promise

我正在尝试兑现诺言,但是似乎当我这样做时:

if (o.TotalCollectionSize - 20 <= index) {
   var selectedserver = games.gameservers[Math.floor(Math.random() * games.gameservers.length)]
   console.log(selectedserver)
   resolve(selectedserver)
   return;
  }

承诺无法解决,但是,如果解决方案不在if语句的范围内,那么解决方案将起作用。

(o.TotalCollectionSize - 20 <= index) 

这句话永远都是正确的,我需要它在到达这一点时停止,这就是为什么我要在这里解决它。

console.log(selectedserver)可以正常工作,并向我显示需要解决的问题。我的问题是,一旦到达需要解决的地步,就不需要了。

getPing(game.placeId, 0).then(function (r) {
            console.log(r)
            res.end(JSON.stringify(r))
      })

getPing是一个返回新promise的函数,(r)值就是要解析的值。如前所述,我的resolve()在if语句之外运行,我不确定为什么它在内部不起作用。我是新来的诺言,所以这可能是一个小问题。

编辑:这是需要看的人的全部功能,

var getPing = function (id,index) {

return new Promise(function (resolve, reject) {


    options.agent = keepAliveAgent
    index = index || 0;

    var r = https.request(options, function (res) {

        var data = []
        res.on('data', function (d) {
            data.push(d)
        }).on('end', function () {
            var buf = Buffer.concat(data)
            var encodingheader = res.headers['content-encoding']
            if (encodingheader == 'gzip') {

                zlib.gunzip(buf, function (err, buffer) {
                    var o = JSON.parse(buffer.toString())
                    // o is what is returned

                    if (o.TotalCollectionSize - 20 <= index) {
                        console.log(o.TotalCollectionSize - 20, '<=', index)
                        var selectedserver = games.gameservers[Math.floor(Math.random() * games.gameservers.length)]
                        console.log(selectedserver)
                        resolve(selectedserver)
                        return;
                    }

                    if (index < o.TotalCollectionSize) {
                        index = index + 10;
                        console.log(index, o.TotalCollectionSize)
                        o.Collection.sort(function (a, b) {
                            return a.Ping > b.Ping
                        })

                        if (typeof (o.Collection[0]) != "undefined") {
                            var playerscapacity = o.Collection[0].PlayersCapacity.charAt(0)
                            if (playerscapacity != o.Collection[0].Capacity) {
                                games.gameservers.push(o.Collection[0])
                            }
                        }
                        getPing(id, index)
                    }

                })
            }
        })
    })

    r.end()
    //reject('end of here')
})
}

就像我提到的那样,所有这些代码都可以很好地工作,直到有时间解决承诺为止。

1 个答案:

答案 0 :(得分:1)

我将试图回答这个问题,而实际上并不知道您的功能应该做什么或应该如何工作(因为您没有告诉我们),所以请耐心等待。

一个有保证的经验法则是new Promise应尽量少用,并且在使用时应尽可能简单。它应该只包含您要承诺的非承诺异步功能,它们仅包含 ,其余逻辑应在根据您从中获得的承诺进行工作。它不应该是装载回调的烂摊子的巨大容器。

在您的情况下,您有两个异步操作:缓冲的HTTP请求和GZIP提取,因此让我们为它们创建单独的函数:

function requestBufferedData(options) {
    return new Promise(function (resolve, reject) {
        // TODO: Needs to reject() in situation where request fails or else
        //       this promise will never complete when there's an error
        var r = https.request(options, function (res) {
            var data = []
            res.on('data', function (d) {
                data.push(d);
            }).on('end', function () {
                resolve({ 
                    data: Buffer.concat(data),
                    encoding: res.headers['content-encoding'],
                });
            });
        });

        r.end();
    });
}

function extractGzip(data) {
    return new Promise(function (resolve, reject) {
        zlib.gunzip(data, function (err, buffer) {
            if (err) { reject(err); }
            else { resolve(buffer); }
        });
    });
}

现在有了这些,我们可以更加轻松地呼吸。在查看了其余代码约10分钟之后,我仍然无法理解它的正面或反面,因此我将不得不遍历它。清楚的是,您有一个递归过程,该过程重试您的HTTP请求,直到找到所需的值为止,因此我们将继续:

function getPing(id, index) {
     options.agent = keepAliveAgent;

     return requestBufferedData(options)
         .then(function (result) {
             if (result.encoding !== 'gzip') {
                 throw new Error('Response is not gzip');
             }

             return extractGzip(result.data);
         })
         .then(JSON.parse)
         .then(function (o) {
             if (o.TotalCollectionSize - 20 <= index) {
                 console.log(o.TotalCollectionSize - 20, '<=', index)
                 var selectedserver = games.gameservers[Math.floor(Math.random() * games.gameservers.length)]
                 console.log(selectedserver)
                 return selectedServer;
             }

             if (index < o.TotalCollectionSize) {
                 var nextIndex = index + 10;
                 console.log(nextIndex, o.TotalCollectionSize)
                 o.Collection.sort(function (a, b) {
                     return a.Ping > b.Ping
                 });

                 if (typeof (o.Collection[0]) != "undefined") {
                     var playerscapacity = o.Collection[0].PlayersCapacity.charAt(0);
                     if (playerscapacity != o.Collection[0].Capacity) {
                         games.gameservers.push(o.Collection[0])
                     }
                 }

                 return getPing(id, nextIndex);
             }

             throw new Error("Didn't match either condition");
         });
}

我相信这会在满足条件时正确地解决诺言,但是我无法对此进行测试,因此,如果您仍然对此有疑问,请告诉我。