RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 555732
Accepted
justyx
justyx
Asked:2020-08-16 03:37:20 +0000 UTC2020-08-16 03:37:20 +0000 UTC 2020-08-16 03:37:20 +0000 UTC

使用带有 for 循环的承诺

  • 772

任务:我从服务器(不是我的)收集地理数据。为此,我形成了对特定坐标区间的请求,并在 for 循环中向服务器发送请求。我将答案写入文件,这样服务器就不会禁止我通过 tor-control 更改 ip 地址。等待响应是使用 promise 实现的。这是理想的。事实上(根据控制台中的日志判断),数据是随机发送的。告诉我哪里走错了。

for (var i = xMin; i <= xMax; i++) {
    for (var k = yMin; k <= yMax; k++) {
        var swp = swPoint(k, i);
        var nep = nePoint(k, i);
        var llsw = pointToLatLong(swp[0], swp[1]);
        var llne = pointToLatLong(nep[0], nep[1]);
        var datatosend = 'fromlat=' + llsw[0].toString() + 'tolat=' + llne[0].toString() + 'fromlng=' + llsw[1].toString() + 'tolng' + llne[1].toString();

        currX = k;
        currY = i;

        filename = "json/" + currX.toString() + "_" + currY.toString() + "_" + zoom.toString() + ".json";

        options.body = datatosend;

        console.log(filename);

        GetData(options)
        .then(body =>{
            return WriteToFile(body, filename);
        })
        .then(() =>{
            return GetNewCircuit();
        })
        .then(() =>{
            console.log('Step finished');
        })
    }
}

从日志来看,原来是在没有等到前面的操作完成的情况下,冲了4次循环。

控制台日志文本:

json/0_0_1.json
json/1_0_1.json
json/0_1_1.json
json/1_1_1.json
Get response
json/1_1_1.json
Circuit changed
Step finished
Get response
json/1_1_1.json
Circuit changed
Step finished
Get response
json/1_1_1.json
Circuit changed
Step finished
Get response
json/1_1_1.json
Circuit changed
Step finished

调用方法:

function GetNewCircuit(){
    return new promise(function(resolve, reject){
        new_identity('127.0.0.1', 9051, cookie, function(err){
            if(!err){
               console.log('Circuit changed');
               resolve()
            } else{
                console.log(err);
                reject(err);
            }
        });
    });
}

function GetData(reqOptions){
    return new promise(function(resolve, reject){
        request(reqOptions, function(error,response,body){
            if(!error && response.statusCode == 200){
                console.log('Get response');
                resolve(body);
            }
            else{
                reject(error);
            }
        });
    });
}

function WriteToFile(dataToWrite, fileToWrite){
    return new promise(function(resolve, reject) {
        fs.writeFile(fileToWrite, dataToWrite, function(err) {
           if(!err){
               console.log(fileToWrite);
               resolve();
           }
           else{
               reject(err);
           }
        }); 
    });
}

我刚刚开始熟悉js,所以如果除了答案之外,您还建议在哪里以及如何最好地结识,我只会很高兴。

javascript
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    Утка Учится Укрываться
    2020-08-16T04:30:53Z2020-08-16T04:30:53Z

    在这段代码中,我同时看到了新手 javascript 开发人员面临的两个主要问题(共三个)。

    问题一——对异步的误解。
    当然,循环不会等到异步操作的结果返回后才可以循环。

    想象一下,您有四只过度活跃的院子梗,您连续向它们扔了四个球。他们将以什么顺序将它们带回来?是的,鬼知道。

    而Promise.then里面是回调,只是写的更方便而已。

    该怎么办?
    Don't:
    第一个想到的方案,但是还是等第一个操作结束,然后在下一次迭代的时候增加循环计数器,开始下一个操作。但是通过这样做,您只是将异步操作转换为同步操作,并失去了异步带来的所有收益。
    需要:
    理解这段代码的主要问题不是异步,而是你不理解闭包。好吧,也就是说,您的控制台json/1_1_1.json多次出现故障是否困扰您?

    问题二:
    对js中作用域的误解,它们也是闭包。关于循环中变量值丢失的问题是中层开发人员面试中排名第一的问题,如果不回答,对话可能会被关闭。在这个资源上,这个问题以不同的形式出现,每周出现几次。例如,在这里它得到了详细的回答(真的没有提到 es6 中的块作用域)。

    那么,也就是说,您的代码中错误的核心看起来像这样:

    for(var i = 0; i<4; i++){
        setTimeout(function(){console.log(i)}, 1000)
    }
    

    setTimeout这里 - 作为最简单的异步操作的例子。如果你不明白这里为什么会显示4乘4,那你就需要琢磨明白了。一定。
    简而言之,发生这种情况是因为 var 变量在 js 中的作用域是一个函数,而不是花括号。循环不形成单独的作用域,所有四次函数都将引用同一个变量 i,指向同一个内存区域。

    好了,我都明白了,我还是要同步。
    为了巧妙地管理管理许多异步请求的流程,有许多公共库,例如async,例如看async.waterfall

    • 8
  2. pitersky
    2020-08-16T23:39:40Z2020-08-16T23:39:40Z

    在循环中将承诺收集到一个数组中,然后使用 Promise.all 等待它们完成

    • 1

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何停止编写糟糕的代码?

    • 3 个回答
  • Marko Smith

    onCreateView 方法重构

    • 1 个回答
  • Marko Smith

    通用还是非通用

    • 2 个回答
  • Marko Smith

    如何访问 jQuery 中的列

    • 1 个回答
  • Marko Smith

    *.tga 文件的组重命名(3620 个)

    • 1 个回答
  • Marko Smith

    内存分配列表C#

    • 1 个回答
  • Marko Smith

    常规赛适度贪婪

    • 1 个回答
  • Marko Smith

    如何制作自己的自动完成/自动更正?

    • 1 个回答
  • Marko Smith

    选择斐波那契数列

    • 2 个回答
  • Marko Smith

    所有 API 版本中的通用权限代码

    • 2 个回答
  • Martin Hope
    jfs *(星号)和 ** 双星号在 Python 中是什么意思? 2020-11-23 05:07:40 +0000 UTC
  • Martin Hope
    hwak 哪个孩子调用了父母的静态方法?还是不可能完成的任务? 2020-11-18 16:30:55 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    Arch ArrayList 与 LinkedList 的区别? 2020-09-20 02:42:49 +0000 UTC
  • Martin Hope
    iluxa1810 哪个更正确使用:if () 或 try-catch? 2020-08-23 18:56:13 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5