向数组添加未定义的方法promise,以便稍后在Promise.all()

时间:2019-01-30 20:00:54

标签: javascript asynchronous vue.js promise pouchdb

我想排队连接后将执行的数据库调用。连接数据库对象后,它会创建并存储为模块的成员。

数据库模块:

var db = {
  localDb: null,
  connectLocal: (dbName) => {
    // Do stuff
    this.localDb = new PouchDB(dbName) // has a allDocs() method
  }
}

将呼叫添加到队列:

var dbQueue = []

function getDocs () {
  dbQueue.push (
    db.localDb.allDocs () // allDocs() not yet defined; returns promise
  )
}

// Called when connected and queue is not empty:
function processQueue () {
  Promise.all (dbQueue)
  .then(...)
}

如果在db.connectLocal()设置db.localDb之前调用getDocs(),则由于未定义db.localDb,我将收到以下错误(或类似错误):

  

TypeError:无法读取未定义的属性'then'

是否可以在数组中添加一个未声明的方法,该方法返回一个Promise,以便稍后在Promise.all()中进行解析?关于如何解决此问题还有其他想法吗?

此外,我正在使用Vue.js和PouchDB。

2 个答案:

答案 0 :(得分:0)

您可以在db模块中做出承诺,而不仅仅是 import React, { Component } from 'react'; export class CheckboxRenderer extends Component{ constructor(props) { super(props); if(this.props.colDef.field==='noRestrictions'){ this.state={ value:true, disable:false }; } else if(this.props.colDef.field==='doNotBuy') { this.state={ value:false, disable:true }; } this.handleCheckboxChange=this.handleCheckboxChange.bind(this); } handleCheckboxChange(event) { //this.props.data.checkbox=!this.props.data.checkbox; ={this.state.show} //this.setState({value: this.props.data.checkbox}); if(this.state.value){this.setState({value: false});} else{this.setState({value: true});} alert(this.state.value); //check for the last row and check for the columnname and enable the other columns } render() { return ( <input type='checkbox' checked={this.state.value} disabled={this.state.disable} onChange={this.handleCheckboxChange}/> ); } } export default CheckboxRenderer; import React, { Component } from 'react'; import './App.css'; import { AgGridReact } from 'ag-grid-react'; import CheckboxRenderer from './CheckboxRenderer'; import 'ag-grid/dist/styles/ag-grid.css'; import 'ag-grid/dist/styles/ag-theme-balham.css'; class App extends Component { constructor(props) { super(props); let enableOtherFields=false; this.state = { columnDefs: [ {headerName: 'Make', field: 'make'}, {headerName: 'noRestrictions', field: 'noRestrictions', cellRendererFramework: CheckboxRenderer, cellRendererParams:{checkedVal:true,disable:false}, onCellClicked: function (event) { // event.node.columnApi.columnController.gridColumns[1].colDef.cellRendererParams.checkedVal=!event.node.columnApi.columnController.gridColumns[1].colDef.cellRendererParams.checkedVal; // event.node.data.checkbox=!event.data.checkbox; let currentNode=event.node.id; event.api.forEachNode((node) => { if(node.id===currentNode) { node.data.checkbox=!node.data.checkbox; } //if(!node.columnApi.columnController.gridColumns[1].colDef.cellRendererParams.checkedVal){ // checkbox is unchecked if(node.data.checkbox===false && node.data.checkbox!=='undefined'){ enableOtherFields=true; } else { enableOtherFields=false; } //alert(node.id); //alert(event.colDef.cellRendererParams.checkedVal); }); alert("enable other fields:"+enableOtherFields); } }, {headerName:'doNotBuy',field:'doNotBuy', cellRendererFramework: CheckboxRenderer, cellRendererParams:{checkedVal:false,disable:true} }, {headerName: 'Price', field: 'price', editable: true} ], rowData: [ {make: "Toyota",noRestrictions:true,doNotBuy:false, price: 35000}, {make: "Ford", noRestrictions:true,doNotBuy:false,price: 32000}, {make: "Porsche", noRestrictions:true,doNotBuy:false, price: 72000} ] }; } componentDidMount() { } render() { return ( <div className="ag-theme-balham" style={{height: '200px', width: '800px'}} > <AgGridReact enableSorting={true} enableFilter={true} //pagination={true} columnDefs={this.state.columnDefs} rowData={this.state.rowData}> </AgGridReact> </div> ); } } export default App; 属性:

localDb

然后,将let localDb = null; let resolveLocalDb = null; let localDbPromise = new Promise(function(resolve, reject) { resolveLocalDb = resolve; }); var db = { getLocalDb: () { return localDbPromise; } connectLocal: (dbName) => { // Do stuff localDb = new PouchDB(dbName) // has a allDocs() method resolveLocalDb(localDb); } } 交换为.localDb,这将返回一个承诺。

getLocalDb()

答案 1 :(得分:0)

我解决了队列问题,但这根本不是我要解决的问题。

我的第一个问题是认为Promise.all()推迟了对我的方法的调用,直到被调用为止,但是将它们添加到数组时会被调用。这导致了我在问题中提到的错误。因此,我需要重新考虑如何使用可能不存在的方法填充队列。

解决方案是将调用作为字符串(例如"getDocs")添加到数组(队列)中,然后使用bracket notation(例如db["getDocs"]())遍历数组调用方法

我的应用程序是用Vue.js编写的,因此显然有所不同,但这是一个简化的工作示例:

// Dummy DB object
var db = {
  docs: [1, 2, 3]
};

// Queue were the DB ops are stored
var dbQueue = [];

// Process the queue - called elsewhere once the DB is connected
// The processed array and Promise.all() aren't necessary as you could just call
// the method outright, but I want to log the results in order
async function processQueue() {
  var processed = []; // Called queue methods

  // Add valid methods to
  dbQueue.forEach(method => {
    if (typeof db[method] === "function") {
      return processed.push(db[method]());
    } else {
      console.error(`"${method}" is not a name of a valid method.`);
    }
  });

    // Log promise results
  await Promise.all(processed).then(res => {
    console.log("Processed:", res);
  });

  // Empty the queue
  dbQueue = [];
}

// Add some calls to the queue of methods that don't yet exist
dbQueue.push("getDocs");
dbQueue.push("getDocs");

// Simulate adding the method
db.getDocs = function() {
  return new Promise(resolve => {
    resolve(this.docs);
  });
};

// Process queue once conditions are met (e.g. db is connected); called elsewhere
processQueue();

这是一个带有示例的小提琴,该示例允许使用方法的参数:https://jsfiddle.net/rjbv0284/1/