【问题标题】:Sequential promises in a Zapier triggerZapier 触发器中的顺序承诺
【发布时间】:2018-09-05 22:23:00
【问题描述】:

我有一个正在从 Web 服务检索数据的 Zapier 触发器(应用程序)。 Web 服务以 500 个项目的块形式返回数据,每个项目包含一个 UNIX 时间戳和一个 Web 服务参数('since')指定您要检索的数据块的开始时间。

为了使其正常工作,我需要按顺序检索数据块,在前一个块中检索的数据允许我找到下一次 Web 服务调用的 'since' 值。

我目前使用的代码:

const fetchItems = (z, bundle, since) => {

    return z.request({

        url: URL_PATH + ':' + URL_PORT + '/v1/items',
        params: {
            since: since
        }

    }).then(( response) => {

        if (response.status === 401) {
            throw new Error('The authentication has expired.');
        } else if (response.status !== 200){
            throw new Error('Status ' + response.status + ' returned.');
        }

        return response.json;
    });
};

const processItems = (z, bundle) => {

    var jsonAll = [];
    var since = 0;
    var jsonLength = ITEM_BLOCK_SIZE;

    return (function loop(i) {

        if (jsonLength === ITEM_BLOCK_SIZE) {

            new Promise((resolve, reject) => {

                fetchTransactions(z, bundle, since).then((json) => {

                    since = json[json.length - 1].modified;
                    jsonLength = json.length;

                    for (j = 0; j < json.length; j++) {

                        jsonAll.push( json[j]);
                    }

                    resolve();
                });

            }).then(loop.bind(null, jsonLength));

        } else {

            return jsonAll;
        }

    })(0);
}

module.exports = {
    ...
    operation: {
        ...
        perform: processItems,
        ...
    }
}; 

我遇到的问题是,当我运行此代码时,Zapier 返回以下错误:Results must be an array, got: undefined, ()

fetchItems() 函数工作正常,它返回指定 'since' 值的数据块。

我在处理 Promise 方面的经验有限,因此我们将不胜感激。

【问题讨论】:

  • fetchTransactions 未定义。应该是...Items
  • 你从哪里得到错误?您没有错误处理程序 (.`catch(err) => {}) 来捕获这些错误。
  • 哦,我开始发现您的代码有问题。您收到的此错误不在此功能范围内。它来自调用processItems(或perform,因为它公开为)的代码。问题是您没有返回等待的承诺,而且您也没有以任何方式将创建这些承诺的操作排队。
  • 感谢您的快速回复。是的,它应该是 fetchItems,我的错,对不起。你能给我任何我需要做的改变的例子吗,我对 Promise 的了解有限,这段代码来自我在互联网上找到的例子。
  • 在您发表评论前 2 分钟添加了一个答案 ;-)

标签: javascript promise zapier


【解决方案1】:

我花了一段时间来解开processItems 的意图,但过了一会儿我掌握了逻辑的窍门。我真的很欣赏 IIFE loop 逻辑的简单之美,因此将其保留在我的版本中,但是您混淆了同步和异步代码如何工作的一些假设(这可能是由于不熟悉 Promise 造成的)。

const processItems = (z, bundle) => {
  const jsonAll = [];
  let since = 0;

  return new Promise((resolve, reject) => {
    (function loop() {
      console.log("inLoop");
      fetchTransactions(z, bundle, since)
        .then(json => {
          const jsonLength = json.length;
          since = json[json.length - 1].modified;

          jsonAll.push(...json);

          if (jsonLength === ITEM_BLOCK_SIZE) {
            loop(jsonLength);
          } else {
            resolve(jsonAll);
          }
        })
        .catch(reject);
    })();
  });
};

// Testdriver (proves it works)
let callCount = 0;
const ITEM_BLOCK_SIZE = 10;
function fetchTransactions() {
  return new Promise(resolve => {
    if (callCount === 5) return resolve([{ modified: 100 }]);
    const list = [];

    for (let i = 0; i < ITEM_BLOCK_SIZE; i++) list.push({ modified: 42 });
    callCount++;

    resolve(list);
  });
}


processItems({},{}).then(results =>
  console.log(
    "results are correct?",
    results.length === 5 * ITEM_BLOCK_SIZE + 1
  )
);

函数作为一个整体是一个async 方法,而代码中的任何return 语句当然都是同步。这就是它返回 undefined 的原因;返回值在函数体执行很久之后才返回!

这就是Promises 闪耀的地方。您可以从您的方法中返回Promise,然后等待稍后完成承诺。这就是失败的原因:您基本上需要在loop 函数中返回一个resolved 的Promise。

所以我补充说,删除了一些我认为不必要的 Promise 创建,并将一些全局状态移动到本地状态。

【讨论】:

  • 非常感谢。我刚刚尝试运行它,但出现以下错误:
  • 抱歉,不应该按回车键。 /private/var/folders/vl/_d19gjdd4sldhbl0bj93_c3h0000gp/T/zapier-d33348fc/triggers/receipe.js:38 return new Promise(resolve, reject) {
  • 所以,它似乎反对左大括号。
  • 是的,我认为它有错误,所以不足为奇:-) 没有支持功能很难运行代码!但是,如果您查看自己的代码,您会发现我错过了 ` => `。现在添加了。
  • 这就是我试图做的,但不幸的是没有运气。你需要 15 声望 - 动作被记录,只是没有显示。
猜你喜欢
  • 1970-01-01
  • 2016-11-10
  • 1970-01-01
  • 1970-01-01
  • 2016-11-23
  • 2019-06-16
  • 2015-12-22
  • 2017-08-18
  • 1970-01-01
相关资源
最近更新 更多