【问题标题】:Need help to 'async' a Function("...").call() for firestore需要帮助来“异步”一个 Function("...").call() for firestore
【发布时间】:2020-09-22 11:40:22
【问题描述】:

各位大师,早安,

我构建了我的代码以允许来自用户的动态输入字符串(sCmd),然后该字符串将被推送到函数中

let res = Function("moment", '"use strict";' + sCmd).call(this, moment);

这是一个用户输入示例,允许他们调用“等待”命令

let sCmd = `
    // ---- cmd START
    function simulateFirebaseGet() {
      return new Promise(resolve => {
        setTimeout(() => {
          resolve('resolved from simulateFirebaseGet()');
        }, 2000);
      });
    }
    async function callAsyncFunc() {
      console.log('#2 - run callAsyncFunc()');

      let res = await simulateFirebaseGet();
      console.log('#3 - start wait 2 sec')
      console.log('#4 -', res);
      console.log('#5 - waited 2 sec')
    }

    console.log('#1 - START Function()');
     callAsyncFunc()
    console.log('#6 - STOP Function()');
    // ---- cmd END
    `;

但它并没有按照我的预期工作。控制台日志

#1 - START Function()
#2 - run callAsyncFunc()
#6 - STOP Function()
#3 - start wait 2 sec
#4 - resolved from simulateFirebaseGet()
#5 - waited 2 sec

我期待下面的东西

#1 - START Function()
#2 - run callAsyncFunc()
#3 - start wait 2 sec
#4 - resolved from simulateFirebaseGet()
#5 - waited 2 sec
#6 - STOP Function()

我还提供了StackBlitz link。如果我把“等待”放在

await callAsyncFunc()

我会收到错误Error: Unexpected identifier

更新: 在@CertainPerformance 回复后,我选择了第二种方法并按顺序运行。凉爽的!但很快我注意到一旦我将调用者更改为

console.log("START OUTSIDE Function()");
let res = Function("moment", '"use strict";' + sCmd).call(
  this,
  moment
); 
console.log("STOP OUTSIDE Function()");

控制台日志输出为

START OUTSIDE Function()
#1 - START Function()
run helper
#2 - run callAsyncFunc()
STOP OUTSIDE Function()
#3 - start wait 2 sec
#4 - resolved from simulateFirebaseGet()
#5 - waited 2 sec
#6 - STOP Function()

我需要它来运行

START OUTSIDE Function()
#1 - START Function()
run helper
#2 - run callAsyncFunc()
#3 - start wait 2 sec
#4 - resolved from simulateFirebaseGet()
#5 - waited 2 sec
#6 - STOP Function()
STOP OUTSIDE Function()

在我的用例中,我必须循环“Function(...).call()”并且它们需要按顺序处理。前面循环中的结果将用于“Function(...).call()”中后面的项中的计算。

【问题讨论】:

    标签: typescript async-await


    【解决方案1】:

    要么在 callAsyncFn() 解析后将 #6 放入 .then 中,要么将整个函数放入 IIFE 以便您可以 await 调用 callAsyncFn

    let sCmd = `
        // ---- cmd START
        function simulateFirebaseGet() {
          return new Promise(resolve => {
            setTimeout(() => {
              resolve('resolved from simulateFirebaseGet()');
            }, 2000);
          });
        }
        async function callAsyncFunc() {
          console.log('#2 - run callAsyncFunc()');
    
          let res = await simulateFirebaseGet();
          console.log('#3 - start wait 2 sec')
          console.log('#4 -', res);
          console.log('#5 - waited 2 sec')
        }
    
        console.log('#1 - START Function()');
         callAsyncFunc().then(() => {
            console.log('#6 - STOP Function()');
            // ---- cmd END
        });
        `;
        let res = Function("moment", '"use strict";' + sCmd).call(this, {});

    let sCmd = `
        // ---- cmd START
        (async () => {
    
          function simulateFirebaseGet() {
            return new Promise(resolve => {
              setTimeout(() => {
                resolve('resolved from simulateFirebaseGet()');
              }, 2000);
            });
          }
          async function callAsyncFunc() {
            console.log('#2 - run callAsyncFunc()');
    
            let res = await simulateFirebaseGet();
            console.log('#3 - start wait 2 sec')
            console.log('#4 -', res);
            console.log('#5 - waited 2 sec')
          }
    
          console.log('#1 - START Function()');
          await callAsyncFunc()
          console.log('#6 - STOP Function()');
          // ---- cmd END
      })();
        `;
        let res = Function("moment", '"use strict";' + sCmd).call(this, {});

    你需要在外面做同样的事情——要么await调用构造函数,要么调用.then

    let sCmd = `
        // ---- cmd START
        function simulateFirebaseGet() {
          return new Promise(resolve => {
            setTimeout(() => {
              resolve('resolved from simulateFirebaseGet()');
            }, 2000);
          });
        }
        async function callAsyncFunc() {
          console.log('#2 - run callAsyncFunc()');
    
          let res = await simulateFirebaseGet();
          console.log('#3 - start wait 2 sec')
          console.log('#4 -', res);
          console.log('#5 - waited 2 sec')
        }
    
        console.log('#1 - START Function()');
        return callAsyncFunc().then(() => {
            console.log('#6 - STOP Function()');
            // ---- cmd END
        });
        `;
    console.log("START OUTSIDE Function()");
    Function("moment", '"use strict";' + sCmd).call(
      this,
      {}
    )
      .then((res) => {
        console.log("STOP OUTSIDE Function()");
      });

    【讨论】:

    • 你的第二种方法奏效了!但在我的用例中,我必须循环“Function().call”,它不会在“Function().call”之外“等待”。我将在我的线程中更新我的逻辑以详细说明。
    • 查看编辑,你需要在内部和外部做同样的事情,这样 Promise 才能正确链接在一起
    • 您的代码有效。但是对于我的用例,我需要以循环形式运行 Function(...).call 。这意味着我无法控制每个实例的数量 Function(...).call 。你的链方法不适合我的用例:(
    猜你喜欢
    • 1970-01-01
    • 2013-07-11
    • 1970-01-01
    • 2021-01-26
    • 2011-02-08
    • 1970-01-01
    • 2017-03-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多