【问题标题】:Can't get promise to work with external function无法承诺使用外部功能
【发布时间】:2025-12-11 03:05:03
【问题描述】:

我正试图将我的头脑围绕在 javascript 承诺上,因为我在我正在从事的项目中需要它们。我尝试了几件事,但从未成功过。

问题来了:

我有一个函数,它通过 websockets 连接到服务器,获取某些信息并将它们作为对象传递。 由于这是异步的,我需要等到此过程完成才能继续处理我得到的信息。

这是获取信息的全局函数:

function getInfos(par1, par2) {

    // Open Websocket connection, ask for infos and wait for Answer/Message.

    OnMessage: function (aEvent, aToken) {
        if (aToken == "JustAString") {

            // Does this work this way? I need to get the "aToken" to the "MyCalltoServer" Function that called this mess here
            return aToken;

           // Tried this to resolve the promise created in the other script.
            resolve(MyCallToServer);
        }
    }
}

这就是我尝试使用现有的 getInfos 函数创建承诺的方式。

var promiseResolve, promiseReject;

var MyCallToServer = new Promise(function(resolve, reject){

promiseResolve = resolve;
promiseReject = reject;

getInfos(par1,par2);


});

MyCallToServer.then(function(){
    console.log("done");
    console.log(aToken);
})

长话短说 - 它根本不起作用。任何帮助是极大的赞赏。问题是我无法改变 getInfos 函数,因为它已经很复杂了(300 个不同答案的案例)。所以我想也许有办法 包括解决其中的承诺?

非常感谢任何帮助!!!

【问题讨论】:

  • 您创建了 promiseResolvepromiseReject,但没有将函数传递给 getInfos - 两个函数都没有被调用,resolvegetInfos 中未定义。
  • 通话会是什么样子? getInfos(par1,par2,promiseResolve) ?
  • 你不能让getInfos返回它自己的承诺吗?
  • 也许,我不知道 :-) 老实说,我还没有完全理解这个原理。你介意给我举个例子吗?

标签: javascript jquery asynchronous promise


【解决方案1】:

不确定为什么OnMessagegetInfos 内或为什么语法是

OnMessage: function (aEvent, aToken) {}

您可以从getInfos() 调用返回Promise,将aToken 传递给resolve(),包括传递给.catch() 的错误处理函数

function getInfos(par1, par2) {

  // Open Websocket connection, ask for infos and wait for Answer/Message.
  return new Promise(function(resolve, reject) {
    function OnMessage(aEvent, aToken) {
        if (aToken == "JustAString") {
            resolve(aToken);
        }
    };
    OnMessage()
  })
}

function MyCallToServer(par1, par1) {
  return getInfos(par1, par2)
}

function handleMyCallToServer(aToken) {
  console.log("done");
  console.log(aToken);
}

function handleMyCallToServerErroir(err) {
  console.log("error");
  console.err(err);
}

MyCallToServer(1, 2)
.then(handleMyCallToServer)
.catch(handleMyCallToServerError)

【讨论】:

  • “OnMessage”是来自 getInfos() 函数中另一个函数的回调,它从服务器返回答案。我只是在这里缩短了它。我必须以某种方式将承诺/解决方案放在那里。
  • PromiseOnMessage 的 Answer 代码中解析
  • 我无法让它工作,控制台告诉我'无法读取未定义的属性'then'。 “OnMessage”不是函数,而是 getInfos() 函数中另一个函数的回调。
  • 这是这里的样子: else if (aToken.reqType == "xyz") { lWSC.close(); return new Promise(function(resolve,reject){ resolve(aToken); }) }
  • 你能改变OnMessage吗?
【解决方案2】:

Promise 不能重复使用。从可以多次调用的参数化函数中创建要解析/拒绝的全局承诺变量无异于设置不可重入的异步代码。不要去那里。

提供异步数据的一种经典方式是使用一个回调函数,它带有两个参数,其中一个是根据操作的最终结果设置的:

 function getInfos( par1, par2, callBack) {

     //  in asynchronous code that successfully delivers dataObject 

          callBack( false, dataObject); // valid data
          return; // from asynchronous service code

     //  in asynchronous code that detected an error

          callBack( error) // no valid data
          return; // from asynchronous service code

  }

通过回调函数调用:

  function callBack( err, data) {
      if( err) {
      //   the bad news
      }
      if( data) {
      // the good news.
      }
  }

或者,您可以通过返回待处理的承诺来承诺getInfos,该承诺在网络操作发生后被解决或拒绝。这可以通过将所有代码(对于getInfos)放在一个 ES6 承诺执行器函数中来实现,该函数在承诺构造期间同步调用:

function getInfos( par1, par2) {
    return new Promise( function(resolve, reject) {
        // initiate getInfos things with supplied par1, par2 values

        // in asynchronous code that successfully created dataObject

             resolve( dataObject);
             return; // from asynchronous service code

        // in asynchronous code that failed
             reject( new Error( "error text");
             return; // from asynchronous service code
    });
}

一些库通过总是返回一个承诺(不需要使用)来提供这两种机制,除了有条件地调用一个回调(如果提供了一个回调)。在这种情况下,我建议简单地承诺getInfos


编辑。注释中的代码复制了一个带有各种解构承诺对象组件和变量的 JQuery“延迟”对象。这是一个我不建议追求的kludge。

一个更简单的解决方案是先修改getInfos以返回一个promise然后替换

$(document).ready(function() {
    var promiseResolve, promiseReject;
    var FunctionThatCallsServerFunction = new Promise(function(resolve, reject) {
       promiseResolve = resolve;
       promiseReject = reject;
       getInfos(par1,par2);
    });
    FunctionThatCallsServerFunction.then(function() {
        console.log("done"); // aToken should be received from the ServerFunction
        console.log(aToken);
    })
})

$(document).ready( function() {
    getInfos( par1, par2)
    .then(function( aToken) {
        console.log("done");
        console.log(aToken);
    })
    .catch( function( err) {
        console.log("An error occurred: ");
        console.log( err);
    });
})

直接使用getInfos返回的promise。请注意

  • 用于履行承诺的值作为参数值传递给由.then 提供的履行处理程序,并且
  • 通常包含一个 catch 子句,以避免在发生错误时 Promise 软件抛出“未处理的承诺拒绝”异常。

【讨论】:

  • 非常感谢您的帮助!我在理解某些事情时仍然有一点问题:我像你说的那样编辑了 getInfos(),并且在我需要完成承诺的 if else 循环中,我添加了 resolve(dataObject)。 “dataObject”代表什么?在循环中,我得到一个对象(aToken),我需要将其传递给调用该函数的函数。在我调用该函数的另一个文件中,这就是我的代码的样子。我做得对吗?
  • $(document).ready(function() { var promiseResolve, promiseReject; var FunctionThatCallsServerFunction = new Promise(function(resolve, reject){ promiseResolve = resolve; promiseReject = reject; getInfos(par1,par2 ); }); FunctionThatCallsServerFunction.then(function(){ console.log("done"); // aToken 应该从 ServerFunction 接收 console.log(aToken); }) });
  • 该问题将操作描述为“将它们作为信息获取并将它们作为对象交付”:交付的对象是我在抽象中称为“数据对象”的对象。如果aToken 是现实中的对象,请改用它。请注意,您不能将数据传递回调用“getInfos”的函数,因为数据是异步获取的(我认为),并且该函数早就返回了。您将数据传递给 promise 反应处理程序(与 then 一起提供),该处理程序对数据进行处理。