为什么我无法访问多个网络电话的结果? [英] Why am I not able to access the result of multiple networking calls?

查看:111
本文介绍了为什么我无法访问多个网络电话的结果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的Node应用程序中,我正在尝试获取包裹的发货数据。我需要一种获取json数据并将其附加到对象或某些东西的方法,以便我可以将其传递到我的渲染页面(使用pug)。



这是我的代码:

  var test; (var i = 0; i< result.length; i ++)

{
var currentNumber = result [i] .trackingNumber;
ups.track(currentNumber,function(err,tracking){
test + = tracking
});
}

res.send(result)

在ups.track里面做的任何事情都没有进入var测试,我不能想到一个更好的方法来做到这一点。任何帮助将不胜感激。

解决方案

首先, ups.track()是一个异步函数。这意味着将来会将其回调称为不确定的时间。所以,循环的运行到完成,启动 result.length 调用 ups。 track(),然后在任何一个已经完成之前,在任何一个已经调用回调之前,您执行 res.send(result) / p>

其次,你没有初始化你的测试变量,所以 test + = ... 不会产生一个很好的结果。



所以,直到所有的结果完成,你才能知道结果。有多种方法可以做到这一点。



低科技计数器



低科技的方式是保持柜台:

  var test =; 

var cntr = 0;
for(var i = 0; i< result.length; i ++){
var currentNumber = result [i] .trackingNumber;
ups.track(currentNumber,function(err,tracking){
test + = tracking;
//看看我们是否完成了所有的ups.track()调用
if(++ cntr === result.length){
res.send(test);
}
});
}

使用Promises



高科技的方式是使用承诺(这有更多的好处可以学习很多其他原因)。虽然承诺在这里只显示适度的好处,但是只要您有需要协调的异步操作序列,它们就会提供巨大的收益,并且还会使错误处理(您在代码示例中忽略的东西)也更简单。



首先,你创建一个promisified版本的 ups.track()这是一个返回承诺解决或拒绝的函数当 ups.track()完成。

  function upsTrack(num) {
return new Promise(function(resolve,reject){
ups.track(num,function(err,tracking)){
err?reject(err):resolve(tracking);
});
});
}

现在,我们将使用的组合。 map()创建一个数组或承诺来自您所有的调用 upsTrack() Promise.all() / code>告诉我们所有这些承诺何时完成。

  Promise.all(result.map(function项目){
return upsTrack(item.trackingNumber);
}))然后(function(allResults){
// allResults是一个跟踪结果数组
//进程该数组转换成你的最终结果并发送
res.send(allResults.join(,));
})。catch(function(err){
// handle error here
res.status(500).end();
});

请注意,此结构还可以摆脱以前的低科技方式定义的多个变量因为不需要 test cntr i 再说一遍



使用Bluebird Promise库

>

而且,您可以通过使用更聪明的诺基亚图书馆(Bluebird)来获取更多的捷径:

  const Promise = require('bluebird'); 
ups = Promise.promisifyAll(ups);

Promise.map(result,function(item){
return ups.trackAsync(item.trackingNumber);
})然后(function(allResults){
// allResults是一个跟踪结果的数组
//将该数组处理为最终结果并发送给
res.send(allResults.join(,));
}) .catch(function(err){
// handle error here
res.status(500).end();
});

Bluebird承诺库在这里有两个有用的东西。它有一个 promisifyAll()方法,它将自动为您提供所有ups对象方法的promisified方法,并且还具有 Promise.map()它只是将 array.map() Promise.all()因为它是一个常用的结构)。



如果您对Promises和Promise库感兴趣,您可能会发现这很有用:



是否仍然有理由使用像Q或BlueBird这样的承诺图书,现在我们有ES6承诺?


In my Node app I am trying to get shipment data for packages. I need a way to get the json data and append it to an object or something so that I can pass it to my render page (using pug).

This is my code:

    var test;

    for(var i = 0; i < result.length; i++) {
        var currentNumber = result[i].trackingNumber;
        ups.track(currentNumber, function(err, tracking) {
            test += tracking
        });
    }

    res.send(result)

It seems that anything I do inside of the ups.track has no scope into the var test, and I can't think of a better way to do this. Any help would be appreciated.

解决方案

First off, ups.track() is an asynchronous function. That means that it will call its callback some indeterminate time in the future. So, your for loop runs to its completion, launching result.length calls to ups.track() and then you do res.send(result) before any of them have completed, before any of them have called their callback.

Secondly, you aren't initializing your test variable so test += ... won't produce a good result.

So, you can't know the results until all of them have completed. There are various ways to do that.

Low-tech Counter

The "low-tech" way to do that is to keep a counter:

var test = "";

var cntr = 0;
for(var i = 0; i < result.length; i++) {
    var currentNumber = result[i].trackingNumber;
    ups.track(currentNumber, function(err, tracking) {
        test += tracking;
        // see if we are done with all the ups.track() calls yet
        if (++cntr === result.length) {
            res.send(test);
        }
    });
}

Using Promises

The higher-tech way is to use promises (this has larger benefits to learn for lots of other reasons). While promises show only modest benefits here, they provide huge benefits as soon as you have sequences of asynchronous operations you need to coordinate and they also make error handling (something you are ignoring in your code example) much simpler too.

First, you make a "promisified" version of ups.track() which is a function that returns a promise that resolves or rejects when ups.track() finishes.

function upsTrack(num) {
    return new Promise(function(resolve, reject) {
        ups.track(num, function(err, tracking) {
           err ? reject(err) : resolve(tracking);
        });
    });
}

Now, we'll use a combination of .map() to create an array or promises from all your calls to upsTrack() and Promise.all() to tell us when all those promises have completed.

Promise.all(result.map(function(item) {
    return upsTrack(item.trackingNumber);
})).then(function(allResults) {
    // allResults is an array of tracking results
    // process that array into your final result and send it
    res.send(allResults.join(","));
}).catch(function(err) {
    // handle error here
    res.status(500).end();
});

Note that this structure also gets rid of multiple variables defined in the previous low-tech way of doing this as there is no need for test, cntr or i any more. Looping structures and functions that process arrays or handle arrays of results take care of all that for us.

Using the Bluebird Promise library

And, you can take even a few more shortcuts by using a smarter promise library like Bluebird:

const Promise = require('bluebird');
ups = Promise.promisifyAll(ups);

Promise.map(result, function(item) {
    return ups.trackAsync(item.trackingNumber);
}).then(function(allResults) {
    // allResults is an array of tracking results
    // process that array into your final result and send it
    res.send(allResults.join(","));
}).catch(function(err) {
    // handle error here
    res.status(500).end();
});

The Bluebird promise library has two useful things here. It has a promisifyAll() method which will make promisified methods of all the ups object methods for you automatically and it also has Promise.map() which just combines array.map() and Promise.all() in one step (since it's a commonly used structure).

If you're interested in Promises and Promise libraries, you may find this useful:

Are there still reasons to use promise libraries like Q or BlueBird now that we have ES6 promises?

这篇关于为什么我无法访问多个网络电话的结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆