可以编写一个只是等待条件为真的承诺吗?

时间:2017-03-14 23:17:51

标签: typescript promise

我正在开发一个使用名为contentRecordHelper的库的项目。当我通过contentRecordHelper.addTitleFilter()运行一个记录对象时,它根据记录的类型用一堆不同的属性填充记录。

之前录制:

{
   "_title": "Test Record",
   "_type": "content",
   "_id": "029828ABF"
}

在通过contentRecordHelper.addTitleFilter()运行后进行记录:

{
   "_title": "Test Record",
   "_type": "content",
   "_id": "029828ABF",
   "server_id": "VAL8378",
   "client_id": "SIRIUS",
   "$titleFilter":"General",
   "$contentFilter": "Standard:ContentRecord",
   "$contentType":"",
   "$systemType":""
}

从上面可以看到,最后添加了两个属性为空的属性:$ contentType和$ systemType。那是因为这两个是由异步函数填充的,该函数在contentRecordHelper.addTitleFilter()中启动,并且在大约1000ms之后被添加。

但是,只要生成此数据,就会将其传递到网格中。如果信息更新,则必须刷新该网格,以便正确显示。幸运的是,有一个grid.refreshGrid()函数可以做到这一点。我一直在调用它超时,所以我的代码看起来像这样:

function addRecordToGrid(record: any): void {
    this.contentRecordHelper.addTitleFilter(record);
    this.grid.rowData.push(record);
    setTimeout(() => {
       this.grid.refreshGrid();
    }, 1000);
}

现在严格来说这很好用,但我的一位资深开发人员向我指出,我们不应该依赖于1000毫秒的硬盘,因为在慢速后端连接的情况下,这并不总是可靠的。他说,相反,我应该使用一个承诺,以便尽快记录。$ systemType&&记录。$ contentType存在,我调用grid.refreshGrid()。他是对的 - 这很有道理。唯一的麻烦是,我以前从未写过一个承诺,几乎我可以找到的每个例子调用一些异步函数,并等待它完成。就我而言,contentRecordHelper.addTitleFilter()几乎立即完成,即使结果的某些部分直到稍后才会出现。

我怎么能写一个承诺,简单就像等待一个条件是真的,例如(记录。$ systemType&&记录。$ contentType)?如果不可能,那么使用承诺解决我的问题的最佳方式是什么?是否可以在不更改contentRecordHelper.addTitleFilter()的情况下执行此操作?该功能背后的机制非常复杂,如果我可以避免对其进行更改,这将为我节省很多压力。

我对我正在研究的项目(以及一般的打字稿)都很陌生,所以如果这很明显,我很抱歉。

3 个答案:

答案 0 :(得分:3)

由于异步代码位于contentRecordHelper.addTitleFilter,它不会帮助您返回承诺,因为您不知道异步操作何时结束。
Javascript是事件驱动的,没有办法等待对象,知道操作完成的唯一方法是在contentRecordHelper.addTitleFilter中添加返回promise的代码。

你可以做的是:

function addRecordToGrid(record: any): Promise<void> {
    this.contentRecordHelper.addTitleFilter(record);

    return new Promise<void>((resolve, reject) => {
       const check = () => {
            setTimeout(() => {
                if (record.$systemType && record.$contentType) {
                    resolve();
                } else {
                    check();
                }
            }, 1000);
        }

        check();
    });
}

然后像这样使用它:

this.addRecordToGrid(record).then(() => this.grid.rowData.push(record));

但是正如你所看到的,它只会保持循环超时直到设置属性,它实际上不知道操作已经结束。

答案 1 :(得分:3)

  

我怎样才能写出一个承诺,简单就是等待条件成立,例如(record.$systemType && record.$contentType)

是的,那是trivially possible。但不,这不是你应该做的。您也可以使用普通setTimeout进行轮询(只要数据不可用,只需重复推迟refreshGrid调用),但此不是高级开发人员的意思< / em>的。

  

他说相反,我应该使用承诺

并且意味着contentRecordHelper.addTitleFilter()应该在完成更新记录时返回一个承诺。然后你会写

function addRecordToGrid(record: any): void {
    this.contentRecordHelper.addTitleFilter(record).then(() => {
        this.grid.refreshGrid();
    });
    this.grid.rowData.push(record);
}

当然,不,如果不改变addTitleFilter,这是不可能的,但是every asynchronous function returns a promise可以简单地链接到return0

答案 2 :(得分:0)

由于contentRecordHelper.addTitleFilter函数是异步的,它应该有一些方法告诉你何时完成。要么返回Promise(正确的方式),要么采用回调(旧的方式),要么在添加标题过滤器时触发事件。

如果它没有做任何这些事情,你无法改变它,那么你将不得不诉诸黑客 - 比如民意调查,就像在尼扎姆的回答中一样。