使用节点蓝鸟。 APIreturns信息来不及

using node bluebird. API returns information too late

我正在尝试弄清楚如何不在 "hhh" myresult 处出现 undefined。发生的事情是 jjj 以 hello 的形式返回,然后我的结果未定义,然后 "here" 返回所有 api 数据。似乎 api 到 return 花费的时间太长,所以它给了我未定义的。发生这种情况时,我无法使用数据更新我的表格。有什么建议么?

var myresult;
soap.createClient(url, function(err, client) {
   client.getShipQuote(args, function(err, result) {
     if (err) {
       console.log(err.message);
     }
     console.log('RESPONSE BODY:');
     console.log("here", result.return.shipQuote[0].chargesCollection);
     myresult = result.return.shipQuote[0].chargesCollection;
});


});
var x="hello";
bluebird.all([x, myresult])
.spread(function(x, myresult){
  console.log("jjj", x);
  console.log("hhh", myresult);
  response.send(x);
});

首先,Bluebird 是一个 "promise" 库。这意味着它根据承诺创建和运作。要将其与异步操作一起使用,您必须有一个 return 承诺的异步操作,而不是需要常规回调的异步操作。通常,如果您开始使用的异步操作没有 return 承诺,那么您可以 "promisify" 通过制作它的新版本使用它支持的回调来推动承诺。然后,您可以将 Bluebird 的所有功能与该功能的新承诺版本一起使用。

Bluebird 本身并没有任何神奇的力量来知道异步操作何时完成。而且,它无权使异步操作看起来是同步的。它提供用于管理和协调异步操作的工具,因此您可以知道它们何时完成、何时有结果以及 if/when 有错误。

您似乎有两个异步操作,一个在另一个 soap.createClient() 内部,另一个在 client.getShipQuote() 内部。而且,看起来您想对它们进行排序,以便调用第一个,然后将结果传递给第二个,然后在其他代码中,您可以使用最终结果。以下是我建议如何使用承诺:

const Promise = require('bluebird');

// make promisified versions of soap methods
// only have to do this once
Promise.promisifyAll(soap);

// call promisified version
soap.createClientAsync(url).then(client => {
    // could perhaps do this only once beforehand if you know how to reach the client.prototype object
    // before a client object is created - requires knowing a little about how the library is structured
    Promise.promisifyAll(client);
    return client.getShipQuoteAsync(args);
}).then(result => {
    // handle final result here
    response.send(...);
}).catch(err => {
    // handle error here - this will catch all prior errors
    console.log(err);
    response.status(500).send(...);
});

如果你只想通过普通的回调编程(没有承诺)来做到这一点,那么你可以这样做:

soap.createClient(url, function(err, client) {
    if (err) {
        console.log(err.message);
        // send error response
        response.status(500).send(...);
    } else {
        client.getShipQuote(args, function(err, result) {
            if (err) {
                console.log(err.message);
                // send error response
                response.status(500).send(...);
            } else {
                let myResult = result.return.shipQuote[0].chargesCollection;
                // send response here
                response.send(...);
            }
        }
    }
});

请注意,在异步编程的所有情况下,您必须在结果可用的回调中使用结果(或在您从那里调用的函数中)。您不能只将结果填充到更高范围的变量中并在该回调之外的代码中使用它,因为您的时间对于该值何时可用是不正确的。这就是为什么您在代码中得到 undefined 的原因,因为您的代码在异步操作完成之前和设置值之前正在检查变量。只有在完成回调中,您才能真正知道该值可用。承诺不会改变这个事实。它们只是让您更容易管理和协调回调。